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 // John Allison 6th October 2019 27 28 #ifndef G4TOOLSSGVIEWER_HH 29 #define G4TOOLSSGVIEWER_HH 30 31 #include "G4VViewer.hh" 32 33 #include "G4ToolsSGSceneHandler.hh" 34 #include "G4Scene.hh" 35 #include "G4VVisCommand.hh" 36 37 #include <tools/fpng> 38 #include <tools/toojpeg> 39 40 #include <tools/sg/device_interactor> 41 #include <tools/sg/separator> 42 #include <tools/sg/ortho> 43 #include <tools/sg/perspective> 44 #include <tools/sg/torche> 45 #include <tools/sg/blend> 46 #include <tools/sg/noderef> 47 #include <tools/sg/keys> 48 49 #include <tools/tokenize> 50 #include <tools/sg/write_paper> 51 52 template <class SG_SESSION,class SG_VIEWER> 53 class G4ToolsSGViewer : public G4VViewer, tools::sg::device_interactor { 54 typedef G4VViewer parent; 55 typedef tools::sg::device_interactor parent_interactor; 56 public: //tools::sg::device_interactor interface. 57 virtual void key_press(const tools::sg::key_down_event& a_event) { 58 fKeyPressed = true; 59 fKeyShift = a_event.key() == tools::sg::key_shift()?true:false; 60 } 61 virtual void key_release(const tools::sg::key_up_event&) {fKeyPressed = false;} 62 virtual void mouse_press(const tools::sg::mouse_down_event& a_event) { 63 fMousePressed = true; 64 fMousePressedX = a_event.x(); 65 fMousePressedY = a_event.y(); 66 } 67 virtual void mouse_release(const tools::sg::mouse_up_event&) {fMousePressed = false;} 68 virtual void mouse_move(const tools::sg::mouse_move_event& a_event) { 69 G4double x = a_event.x(); 70 G4double y = a_event.y(); 71 G4double dx = x-fMousePressedX; 72 G4double dy = y-fMousePressedY; 73 fMousePressedX = x; 74 fMousePressedY = y; 75 76 if (fMousePressed) { 77 78 if (fKeyPressed && fKeyShift) { // Translation (pan) 79 80 const G4double sceneRadius = fSGSceneHandler.GetScene()->GetExtent().GetExtentRadius(); 81 const G4double scale = 300; // Roughly pixels per window, empirically chosen 82 const G4double dxScene = dx*sceneRadius/scale; 83 const G4double dyScene = dy*sceneRadius/scale; 84 fVP.IncrementPan(-dxScene,dyScene); 85 86 } else { // Rotation 87 88 // Simple ad-hoc algorithms 89 const G4Vector3D& x_prime = fVP.GetViewpointDirection().cross(fVP.GetUpVector()); 90 const G4Vector3D& y_prime = x_prime.cross(fVP.GetViewpointDirection()); 91 const G4double scale = 200; // Roughly pixels per window, empirically chosen 92 G4Vector3D newViewpointDirection = fVP.GetViewpointDirection(); 93 newViewpointDirection += dx*x_prime/scale; 94 newViewpointDirection += dy*y_prime/scale; 95 fVP.SetViewpointDirection(newViewpointDirection.unit()); 96 97 if (fVP.GetRotationStyle() == G4ViewParameters::freeRotation) { 98 G4Vector3D newUpVector = fVP.GetUpVector(); 99 newUpVector += dx*x_prime/scale; 100 newUpVector += dy*y_prime/scale; 101 fVP.SetUpVector(newUpVector.unit()); 102 } 103 } 104 } 105 106 SetView(); 107 DrawView(); 108 } 109 virtual void wheel_rotate(const tools::sg::wheel_rotate_event& a_event) { 110 const G4double angleY = a_event.angle(); 111 if (fVP.GetFieldHalfAngle() == 0.) { // Orthographic projection 112 const G4double scale = 500; // Empirically chosen 113 fVP.MultiplyZoomFactor(1.+angleY/scale); 114 } else { // Perspective projection 115 const G4double delta = fSceneHandler.GetExtent().GetExtentRadius()/200.; // Empirical 116 fVP.SetDolly(fVP.GetDolly()+angleY*delta); 117 } 118 SetView(); 119 DrawView(); 120 } 121 public: 122 G4ToolsSGViewer(SG_SESSION& a_session,G4ToolsSGSceneHandler& a_scene_handler, const G4String& a_name) 123 :parent(a_scene_handler,a_scene_handler.IncrementViewCount(),a_name) 124 ,fSGSession(a_session) 125 ,fSGSceneHandler(a_scene_handler) 126 ,fSGViewer(nullptr) 127 ,fKeyPressed(false) 128 ,fKeyShift(false) 129 ,fMousePressed(false) 130 ,fMousePressedX(0) 131 ,fMousePressedY(0) 132 { 133 //::printf("debug : G4ToolsSGViewer::G4ToolsSGViewer: %lu, %s\n",this,a_name.c_str()); 134 Messenger::Create(); 135 } 136 137 virtual ~G4ToolsSGViewer() { 138 //::printf("debug : G4ToolsSGViewer::~G4ToolsSGViewer: %lu\n",this); 139 //WARNING : nodes may refer f_gl2ps_mgr, f_zb_mgr (to handle gstos (for GPU) or textures), then 140 // we have to delete them first. 141 fSGViewer->sg().clear(); 142 delete fSGViewer; 143 } 144 protected: 145 G4ToolsSGViewer(const G4ToolsSGViewer& a_from) 146 :parent(a_from) 147 ,parent_interactor(a_from) 148 ,fSGSession(a_from.fSGSession) 149 ,fSGSceneHandler(a_from.fSGSceneHandler) 150 ,fSGViewer(nullptr) 151 ,fKeyPressed(false) 152 ,fKeyShift(false) 153 ,fMousePressed(false) 154 ,fMousePressedX(0) 155 ,fMousePressedY(0) 156 {} 157 G4ToolsSGViewer& operator=(const G4ToolsSGViewer&) {return *this;} 158 public: 159 virtual void Initialise() { 160 if(fSGViewer) return; //done. 161 fVP.SetAutoRefresh(true); 162 fDefaultVP.SetAutoRefresh(true); 163 //::printf("debug : G4ToolsSGViewer::Initialise\n"); 164 ////////////////////////////////////////////////////////// 165 /// create the viewer, set the scene graph /////////////// 166 ////////////////////////////////////////////////////////// 167 fSGViewer = new SG_VIEWER(fSGSession 168 ,fVP.GetWindowAbsoluteLocationHintX(1440) 169 ,fVP.GetWindowAbsoluteLocationHintY(900) 170 ,fVP.GetWindowSizeHintX() 171 ,fVP.GetWindowSizeHintY() 172 ,fName); 173 if(!fSGViewer->has_window()) { 174 fViewId = -1; // This flags an error. 175 G4cerr << "G4ToolsSGViewer::Initialise : SG_VIEWER::has_window() failed." << G4endl; 176 return; 177 } 178 fSGViewer->set_device_interactor(this); 179 } 180 181 virtual void SetView() { 182 //::printf("debug : G4ToolsSGViewer::SetView\n"); 183 if(!fSceneHandler.GetScene()) { 184 fSGViewer->set_clear_color(0.3,0.3,0.3,1); //some grey color to signal the user that something is wrong. 185 G4cerr << "G4ToolsSGViewer::SetView : no G4Scene.." << G4endl; 186 return; 187 } 188 189 ////////////////////////////////////////////////////////// 190 ////////////////////////////////////////////////////////// 191 ////////////////////////////////////////////////////////// 192 // Get radius of scene, etc. 193 // Note that this procedure properly takes into account zoom, dolly and pan. 194 const G4Point3D targetPoint 195 = fSceneHandler.GetScene()->GetStandardTargetPoint() + fVP.GetCurrentTargetPoint (); 196 G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius(); 197 if(radius<=0.) radius = 1.; 198 const G4double cameraDistance = fVP.GetCameraDistance (radius); 199 const G4Point3D cameraPosition = targetPoint + cameraDistance * fVP.GetViewpointDirection().unit(); 200 const G4Normal3D& up = fVP.GetUpVector (); 201 const G4double pnear = fVP.GetNearDistance (cameraDistance, radius); 202 const G4double pfar = fVP.GetFarDistance (cameraDistance, pnear, radius); 203 //const G4double right = fVP.GetFrontHalfHeight (pnear, radius); 204 //const G4double left = -right; 205 const G4double top = fVP.GetFrontHalfHeight (pnear, radius); 206 const G4double bottom = -top; 207 // sanity check : 208 tools::vec3f dir(float(targetPoint.x()-cameraPosition.x()), 209 float(targetPoint.y()-cameraPosition.y()), 210 float(targetPoint.z()-cameraPosition.z())); 211 if(!dir.length()) { 212 fSGViewer->set_clear_color(0.3,0.3,0.3,1); 213 G4cerr << "G4ToolsSGViewer::SetView : null size viewer area." << G4endl; 214 return; 215 } 216 217 ////////////////////////////////////////////////////////// 218 ////////////////////////////////////////////////////////// 219 ////////////////////////////////////////////////////////// 220 /* 221 G4cout << "debug : 0002 : radius " << radius << std::endl; 222 G4cout << "debug : cameraDistance : " << cameraDistance << std::endl; 223 G4cout << "debug : fieldHalfAngle : " << fVP.GetFieldHalfAngle() << std::endl; 224 G4cout << "debug : zoomFactor : " << fVP.GetZoomFactor() << std::endl; 225 G4cout << "debug : up : " << up.x() << " " << up.y() << " " << up.z() << std::endl; 226 G4cout << "debug : targetPoint : " << targetPoint.x() << " " << targetPoint.y() << " " << targetPoint.z() << std::endl; 227 G4cout << "debug : cameraPosition : " << cameraPosition.x() << " " << cameraPosition.y() << " " << cameraPosition.z() << std::endl; 228 G4cout << "debug : camera : znear " << pnear << ", zfar " << pfar << std::endl; 229 */ 230 ////////////////////////////////////////////////////////// 231 /// create scene graph /////////////////////////////////// 232 ////////////////////////////////////////////////////////// 233 // Set projection, then create the tools::sg camera node : 234 tools::sg::base_camera* _camera = nullptr; 235 if (fVP.GetFieldHalfAngle() <= 0.) { 236 //G4cout << "debug : camera : ortho : top " << top << " bottom " << bottom << " top-bottom " << top-bottom << std::endl; 237 if((top-bottom)<=0) { 238 fSGViewer->set_clear_color(0.3,0.3,0.3,1); 239 G4cerr << "G4ToolsSGViewer::SetView : for ortho camera, (top-bottom)<=0." << G4endl; 240 return; 241 } 242 tools::sg::ortho* ortho_camera = new tools::sg::ortho; 243 ortho_camera->height.value(float(top-bottom)); 244 _camera = ortho_camera; 245 } else { 246 //G4cout << "debug : camera : perspec : heightAngle " << float(2*fVP.GetFieldHalfAngle()) << std::endl; 247 tools::sg::perspective* perspective_camera = new tools::sg::perspective; 248 perspective_camera->height_angle.value(float(2*fVP.GetFieldHalfAngle())); 249 _camera = perspective_camera; 250 } 251 252 _camera->position.value 253 (tools::vec3f(float(cameraPosition.x()), 254 float(cameraPosition.y()), 255 float(cameraPosition.z()))); 256 _camera->znear.value(float(pnear)); 257 _camera->zfar.value(float(pfar)); 258 259 _camera->look_at(dir,tools::vec3f(up.x(),up.y(),up.z())); //same logic as in G4OpenInventorViewer. 260 261 /* 262 const G4Vector3D& lightDirection = fVP.GetLightpointDirection(); 263 G4cout << "debug : lightDirection : " << lightDirection.x() << " " << lightDirection.y() << " " << lightDirection.z() << std::endl; 264 const G4Vector3D& actualLightDirection = fVP.GetActualLightpointDirection(); 265 G4cout << "debug : actualLightDirection : " << actualLightDirection.x() << " " << actualLightDirection.y() << " " << actualLightDirection.z() << std::endl; 266 */ 267 268 CreateSG(_camera,fVP.GetActualLightpointDirection()); 269 270 {G4Color background = fVP.GetBackgroundColour (); 271 fSGViewer->set_clear_color(float(background.GetRed()),float(background.GetGreen()),float(background.GetBlue()),1);} 272 } 273 274 virtual void ClearView() {} 275 276 virtual void DrawView() { 277 if (!fNeedKernelVisit) KernelVisitDecision(); 278 G4bool kernelVisitWasNeeded = fNeedKernelVisit; // Keep (ProcessView resets). 279 fLastVP = fVP; 280 ProcessView(); // Clears store and processes scene only if necessary. 281 if (kernelVisitWasNeeded) { 282 // We might need to do something if the kernel was visited. 283 } else { 284 } 285 FinishView (); // Flush streams and/or swap buffers. 286 } 287 288 virtual void ShowView() {FinishView();} 289 290 virtual void FinishView() { 291 if(fSGViewer) { 292 fSGSceneHandler.TouchPlotters(fSGViewer->sg()); 293 fSGViewer->show(); 294 fSGViewer->win_render(); 295 fSGSession.sync(); 296 } 297 } 298 299 virtual void SwitchToVisSubThread() {} 300 301 virtual void SwitchToMasterThread() { 302 if (G4Threading::IsMultithreadedApplication()) { 303 // I have not figured out how to draw during a run. 304 // 305 // Setting fNeedKernelVisit=true causes scene deletion and a complete rebuild, 306 // including trajectories, hits, etc. from kept events. 307 // 308 // Clearly this is a limitation because even if you run 1000 events you only 309 // get those kept (default 100), and even worse, if end-if-event-action is 310 // "refresh", you only get one event (the last I think). 311 // 312 // Also, strictly, there is no need to rebuid run-duration models (detector), 313 // but a complete rebuild is the easiest way (already imeplemented). 314 // 315 // Only do this if there are end-of-event models (e.g., trajectories) that 316 // may require it. 317 if (fSceneHandler.GetScene() && fSceneHandler.GetScene()->GetEndOfEventModelList().size()) { 318 fNeedKernelVisit = true; 319 DrawView(); // Draw trajectories, etc., from kept events 320 } 321 } 322 } 323 324 //SG_VIEWER* sg_viewer() {return fSGViewer;} 325 protected: 326 void KernelVisitDecision () { 327 if (CompareForKernelVisit(fLastVP)) { 328 NeedKernelVisit (); // Sets fNeedKernelVisit. 329 } 330 } 331 332 G4bool CompareForKernelVisit(G4ViewParameters& vp) { 333 // Typical comparison. Taken from OpenInventor. 334 if ( 335 (vp.GetDrawingStyle () != fVP.GetDrawingStyle ()) || 336 (vp.GetNumberOfCloudPoints() != fVP.GetNumberOfCloudPoints()) || 337 (vp.IsAuxEdgeVisible () != fVP.IsAuxEdgeVisible ()) || 338 (vp.IsCulling () != fVP.IsCulling ()) || 339 (vp.IsCullingInvisible () != fVP.IsCullingInvisible ()) || 340 (vp.IsDensityCulling () != fVP.IsDensityCulling ()) || 341 (vp.IsCullingCovered () != fVP.IsCullingCovered ()) || 342 (vp.GetCBDAlgorithmNumber() != 343 fVP.GetCBDAlgorithmNumber()) || 344 (vp.IsSection () != fVP.IsSection ()) || 345 (vp.IsCutaway () != fVP.IsCutaway ()) || 346 // This assumes use of generic clipping (sectioning, slicing, 347 // DCUT, cutaway). If a decision is made to implement locally, 348 // this will need changing. See G4OpenGLViewer::SetView, 349 // G4OpenGLStoredViewer.cc::CompareForKernelVisit and 350 // G4OpenGLStoredSceneHander::CreateSection/CutawayPolyhedron. 351 (vp.IsExplode () != fVP.IsExplode ()) || 352 (vp.GetNoOfSides () != fVP.GetNoOfSides ()) || 353 (vp.GetGlobalMarkerScale() != fVP.GetGlobalMarkerScale()) || 354 (vp.GetGlobalLineWidthScale() != fVP.GetGlobalLineWidthScale()) || 355 (vp.IsMarkerNotHidden () != fVP.IsMarkerNotHidden ()) || 356 (vp.GetDefaultVisAttributes()->GetColour() != 357 fVP.GetDefaultVisAttributes()->GetColour()) || 358 (vp.GetDefaultTextVisAttributes()->GetColour() != 359 fVP.GetDefaultTextVisAttributes()->GetColour()) || 360 (vp.GetBackgroundColour ()!= fVP.GetBackgroundColour ())|| 361 (vp.IsPicking () != fVP.IsPicking ()) || 362 // Scaling for Open Inventor is done by the scene handler so it 363 // needs a kernel visit. (In this respect, it differs from the 364 // OpenGL drivers, where it's done in SetView.) 365 (vp.GetScaleFactor () != fVP.GetScaleFactor ()) || 366 (vp.GetVisAttributesModifiers() != 367 fVP.GetVisAttributesModifiers()) || 368 (vp.IsSpecialMeshRendering() != 369 fVP.IsSpecialMeshRendering()) || 370 (vp.GetSpecialMeshRenderingOption() != 371 fVP.GetSpecialMeshRenderingOption()) 372 ) 373 return true; 374 375 if (vp.IsDensityCulling () && 376 (vp.GetVisibleDensity () != fVP.GetVisibleDensity ())) 377 return true; 378 379 if (vp.GetCBDAlgorithmNumber() > 0) { 380 if (vp.GetCBDParameters().size() != fVP.GetCBDParameters().size()) return true; 381 else if (vp.GetCBDParameters() != fVP.GetCBDParameters()) return true; 382 } 383 384 if (vp.IsSection () && 385 (vp.GetSectionPlane () != fVP.GetSectionPlane ())) 386 return true; 387 388 if (vp.IsCutaway ()) { 389 if (vp.GetCutawayMode() != fVP.GetCutawayMode()) return true; 390 if (vp.GetCutawayPlanes ().size () != 391 fVP.GetCutawayPlanes ().size ()) return true; 392 for (size_t i = 0; i < vp.GetCutawayPlanes().size(); ++i) 393 if (vp.GetCutawayPlanes()[i] != fVP.GetCutawayPlanes()[i]) 394 return true; 395 } 396 397 if (vp.IsExplode () && 398 (vp.GetExplodeFactor () != fVP.GetExplodeFactor ())) 399 return true; 400 401 if (vp.IsSpecialMeshRendering() && 402 (vp.GetSpecialMeshVolumes() != fVP.GetSpecialMeshVolumes())) 403 return true; 404 405 return false; 406 } 407 // void keyPressEvent (KeyEvent*); 408 // void keyReleaseEvent (KeyEvent*); 409 // void mouseDoubleClickEvent(MouseEvent*); 410 // void mouseMoveEvent (MouseEvent*); 411 // void mousePressEvent (MouseEvent*); 412 // void mouseReleaseEvent (MouseEvent*); 413 // void wheelEvent (WheelEvent*); 414 415 protected: 416 void CreateSG(tools::sg::base_camera* a_camera,const G4Vector3D& a_light_dir) { 417 tools::sg::group& _parent = fSGViewer->sg(); 418 _parent.clear(); 419 420 /////////////////////////////////////////////////// 421 /// 2D scene graph: /////////////////////////////// 422 /////////////////////////////////////////////////// 423 tools::sg::separator* scene_2D = new tools::sg::separator; 424 _parent.add(scene_2D); 425 scene_2D->add(new tools::sg::noderef(fSGSceneHandler.GetTransient2DObjects())); 426 scene_2D->add(new tools::sg::noderef(fSGSceneHandler.GetPersistent2DObjects())); 427 428 /////////////////////////////////////////////////// 429 /// 3D scene graph: /////////////////////////////// 430 /////////////////////////////////////////////////// 431 tools::sg::separator* scene_3D = new tools::sg::separator; 432 _parent.add(scene_3D); 433 434 scene_3D->add(a_camera); 435 436 {tools::sg::torche* light = new tools::sg::torche; 437 light->on = true; 438 light->direction = tools::vec3f(-a_light_dir.x(),-a_light_dir.y(),-a_light_dir.z()); 439 light->ambient = tools::colorf(0.2f,0.2f,0.2f,1.0f); //same as in G4OpenGLViewer.cc glLight(GL_LIGHT0,GL_AMBIENT and GL_DIFFUSE). 440 light->color = tools::colorf(0.8f,0.8f,0.8f,1.0f); //idem. 441 scene_3D->add(light);} 442 443 {tools::sg::blend* blend = new tools::sg::blend; 444 blend->on = true; //to handle transparency. 445 scene_3D->add(blend);} 446 447 scene_3D->add(new tools::sg::noderef(fSGSceneHandler.GetTransient3DObjects())); 448 scene_3D->add(new tools::sg::noderef(fSGSceneHandler.GetPersistent3DObjects())); 449 } 450 451 void Export(const G4String& a_format,const G4String& a_file,G4bool a_do_transparency) { 452 if(!fSGViewer) return; 453 const G4Colour& back_color = fVP.GetBackgroundColour(); 454 bool top_to_bottom = false; //if using tools::fpng, tools::toojpeg. 455 if(!tools::sg::write_paper(G4cout,f_gl2ps_mgr,f_zb_mgr, 456 tools::fpng::write,tools::toojpeg::write, 457 float(back_color.GetRed()),float(back_color.GetGreen()),float(back_color.GetBlue()),float(back_color.GetAlpha()), 458 fSGViewer->sg(),fSGViewer->width(),fSGViewer->height(), 459 a_file,a_format,a_do_transparency,top_to_bottom,std::string(),std::string())) { 460 G4cout << "G4ToolsSGViewer::Export: write_paper() failed." << G4endl; 461 return; 462 } 463 } 464 465 protected: 466 class Messenger: public G4VVisCommand { 467 public: 468 static void Create() {static Messenger s_messenger;} 469 private: 470 Messenger() { 471 G4UIparameter* parameter; 472 ////////////////////////////////////////////////////////// 473 ////////////////////////////////////////////////////////// 474 write_scene = new G4UIcommand("/vis/tsg/export", this); 475 write_scene->SetGuidance("Write the content of the current viewer in a file at various formats."); 476 write_scene->SetGuidance("Default file is out.eps and default format is gl2ps_eps."); 477 write_scene->SetGuidance("Available formats are:"); 478 write_scene->SetGuidance("- gl2ps_eps: gl2ps producing eps"); 479 write_scene->SetGuidance("- gl2ps_ps: gl2ps producing ps"); 480 write_scene->SetGuidance("- gl2ps_pdf: gl2ps producing pdf"); 481 write_scene->SetGuidance("- gl2ps_svg: gl2ps producing svg"); 482 write_scene->SetGuidance("- gl2ps_tex: gl2ps producing tex"); 483 write_scene->SetGuidance("- gl2ps_pgf: gl2ps producing pgf"); 484 write_scene->SetGuidance("- zb_ps: tools::sg offscreen zbuffer put in a PostScript file."); 485 write_scene->SetGuidance("- zb_png: tools::sg offscreen zbuffer put in a png file."); 486 write_scene->SetGuidance("- zb_jpeg: tools::sg offscreen zbuffer put in a jpeg file."); 487 488 parameter = new G4UIparameter("format",'s',true); 489 parameter->SetDefaultValue("gl2ps_eps"); 490 write_scene->SetParameter (parameter); 491 492 parameter = new G4UIparameter("file",'s',true); 493 parameter->SetDefaultValue("out.eps"); 494 write_scene->SetParameter (parameter); 495 496 parameter = new G4UIparameter ("do_transparency", 'b', true); 497 parameter->SetDefaultValue ("true"); 498 write_scene->SetParameter (parameter); 499 500 } 501 virtual ~Messenger() { 502 delete write_scene; 503 } 504 public: 505 virtual void SetNewValue(G4UIcommand* a_cmd,G4String a_value) { 506 G4VisManager::Verbosity verbosity = GetVisManager()->GetVerbosity(); 507 G4VViewer* viewer = GetVisManager()->GetCurrentViewer(); 508 if (!viewer) { 509 if (verbosity >= G4VisManager::errors) G4cerr << "ERROR: No current viewer." << G4endl; 510 return; 511 } 512 G4ToolsSGViewer* tsg_viewer = dynamic_cast<G4ToolsSGViewer*>(viewer); 513 if(!tsg_viewer) { 514 G4cout << "G4ToolsSGViewer::SetNewValue:" 515 << " current viewer is not a G4ToolsSGViewer." << G4endl; 516 return; 517 } 518 std::vector<std::string> args; 519 tools::double_quotes_tokenize(a_value,args); 520 if(args.size()!=a_cmd->GetParameterEntries()) return; 521 if(a_cmd==write_scene) { 522 G4bool do_transparency = G4UIcommand::ConvertToBool(args[2].c_str()); 523 tsg_viewer->Export(args[0],args[1],do_transparency); 524 } 525 } 526 private: 527 G4UIcommand* write_scene; 528 }; 529 530 protected: 531 SG_SESSION& fSGSession; 532 G4ToolsSGSceneHandler& fSGSceneHandler; 533 SG_VIEWER* fSGViewer; 534 G4ViewParameters fLastVP; // Memory for making kernel visit decisions. 535 536 G4bool fKeyPressed; 537 G4bool fKeyShift; 538 G4bool fMousePressed; 539 G4double fMousePressedX, fMousePressedY; 540 541 tools::sg::zb_manager f_zb_mgr; 542 tools::sg::gl2ps_manager f_gl2ps_mgr; 543 544 }; 545 546 #endif 547