Import Geant4 11.3.0 source tree
This commit is contained in:
@@ -6,6 +6,62 @@ It must **not** be used as a substitute for writing good git commit messages!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## 2024-09-13 John Allison (opengl-V11-02-09)
|
||||
- G4OpenGLStoredQtSceneHandler.cc:
|
||||
- G4OpenGLStoredQtSceneHandler::ClearStore():
|
||||
- Commented out some code related to the old scene tree. The old scene
|
||||
tree is currently (partially) disabled, but this code somehow affects
|
||||
the view in rare cases, e.g., after twinkling the volume does not return
|
||||
to its original colour. So I have disabled this, pending a review of
|
||||
the old scene tree.
|
||||
|
||||
## 2024-10-25 John Allison (opengl-V11-02-08)
|
||||
- G4OpenGLQtViewer.cc:
|
||||
- G4OpenGLQtViewer::currentTabActivated(): Fix compilation error, see Bug Report 2633.
|
||||
- Use .data().
|
||||
|
||||
## 2024-09-13 John Allison (opengl-V11-02-07)
|
||||
- G4OpenGLQtViewer.cc:
|
||||
- Comment out code that refers to the old scene tree because it adversely impacts
|
||||
the new scene tree.
|
||||
- I would like to extract the old scene tree code completely, but so far I have
|
||||
found it difficult, since it is so entangled with other code. So my efforts so
|
||||
far have been to bop problems on the head as they arise. Not satisfactory, I
|
||||
know, and I will continue to work on it.
|
||||
|
||||
## 2024-08-13 John Allison (opengl-V11-02-06)
|
||||
- G4OpenGLQtViewer:
|
||||
- Resolve the timing issues around switching to the vis sub-thread with the
|
||||
use of G4CONDITIONWAITLAMBDA.
|
||||
- Fix small memory leak in G4OpenGLQtViewer::DrawText.
|
||||
|
||||
## 2024-07-24 Guy Barrand (opengl-V11-02-05)
|
||||
- G4OpenGLImmediateQtViewer, G4OpenGLStoredQtViewer::ShowView: Qt6: do a:
|
||||
((QApplication*)G4Qt::getInstance ())->processEvents();
|
||||
so that a:
|
||||
/vis/viewer/interpolate viewfiles/movie-1
|
||||
produces truly an animation.
|
||||
|
||||
## 2024-07-12 Guy Barrand (opengl-V11-02-04)
|
||||
- G4OpenGLQtViewer: Qt6: implement ReadyToDraw(). It permits to avoid a crash in case
|
||||
of /run/beamOn in vis.mac at startup (especially on macOS).
|
||||
- G4OpenGLImmediateQtViewer, G4OpenGLStoredQtViewer: Qt5: in Initialise(), displace
|
||||
makeCurrent() after CreateMainWindow(). It avoids a crash in case of /run/beamOn
|
||||
in vis.mac at startup.
|
||||
- G4OpenGLQtViewer: Qt5, Qt6: in DoneWithVisSubThread(), SwitchToMasterThread() protect
|
||||
against a possible null qGLW->context(). It permits to avoid a crash in case of
|
||||
doing /run/beamOn in vis.mac at startup.
|
||||
- G4OpenGLQtViewer, G4OpenGLImmediateQtViewer, G4OpenGLStoredQtViewer: Qt6:
|
||||
remove unused fields: fHasToRepaint, fUpdateGLLock, fQGLWidgetInitialiseCompleted
|
||||
and fPaintEventLock.
|
||||
- G4OpenGLImmediateQtViewer, G4OpenGLStoredQtViewer: Qt6: remove no more needed
|
||||
initializeGL() and showEvent() methods.
|
||||
- G4OpenGLImmediateQtViewer, G4OpenGLStoredQtViewer: Qt6: displace setExportImageFormat("jpg")
|
||||
in Initialise().
|
||||
|
||||
## 2024-06-21 Ben Morgan (opengl-V11-02-03)
|
||||
- Use runtime checks for MT mode where possible.
|
||||
|
||||
## 2024-05-30 Guy Barrand (opengl-V11-02-02)
|
||||
- G4OpenGLImmediateQtViewer, G4OpenGLStoredQtViewer: Qt6: remove the usage of a paintEvent(),
|
||||
the paintGL() should be sufficient. Having an extra paintEvent() is confusing.
|
||||
|
||||
@@ -47,7 +47,9 @@ public:
|
||||
const G4String& name = "");
|
||||
~G4OpenGLImmediateQtViewer ();
|
||||
void Initialise ();
|
||||
#if QT_VERSION < 0x060000
|
||||
void initializeGL ();
|
||||
#endif
|
||||
void DrawView ();
|
||||
void resizeGL(int width,int height);
|
||||
void paintGL();
|
||||
@@ -66,7 +68,9 @@ public:
|
||||
}
|
||||
#endif
|
||||
protected:
|
||||
#if QT_VERSION < 0x060000
|
||||
void showEvent(QShowEvent * event );
|
||||
#endif
|
||||
void wheelEvent(QWheelEvent *event);
|
||||
void mousePressEvent(QMouseEvent *event);
|
||||
void mouseMoveEvent(QMouseEvent *event);
|
||||
|
||||
@@ -97,7 +97,17 @@ public:
|
||||
G4OpenGLQtViewer (G4OpenGLSceneHandler& scene);
|
||||
virtual ~G4OpenGLQtViewer ();
|
||||
#ifdef G4MULTITHREADED
|
||||
// In MT mode these functions are called in the following order for each run:
|
||||
// For switching threads in MT mode
|
||||
// Note: the order of calling of MovingToVisSubThread and SwitchToVisSubThread
|
||||
// is undefined, so we have to use mutexes to ensure required information,
|
||||
// namely the vis sub-thread address, is available before moving objects.
|
||||
// To summarise, the order of calling is
|
||||
// DoneWithMasterThread
|
||||
// MovingToVisSubThread ) or ( SwitchToVisSubThread
|
||||
// SwitchToVisSubThread ) ( MovingToVisSubThread
|
||||
// DoneWithVisSubThread
|
||||
// MovingToMasterThread
|
||||
// SwitchToMasterThread
|
||||
// Called on the master thread before starting the vis sub-thread.
|
||||
virtual void DoneWithMasterThread ();
|
||||
// Called on the master thread after starting the vis sub-thread.
|
||||
@@ -116,6 +126,7 @@ private:
|
||||
G4OpenGLQtViewer (const G4OpenGLQtViewer&);
|
||||
G4OpenGLQtViewer& operator= (const G4OpenGLQtViewer&);
|
||||
public:
|
||||
virtual G4bool ReadyToDraw();
|
||||
virtual void updateQWidget()=0;
|
||||
void updateSceneTreeWidget();
|
||||
void updateViewerPropertiesTableWidget();
|
||||
@@ -194,10 +205,12 @@ protected:
|
||||
void savePPMToTemp();
|
||||
int fRecordFrameNumber;
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
bool fHasToRepaint;
|
||||
bool fUpdateGLLock;
|
||||
bool fQGLWidgetInitialiseCompleted;
|
||||
bool fPaintEventLock;
|
||||
#endif
|
||||
|
||||
// Flag to indicate that action was initiated by interaction (mouse
|
||||
// click) on the scene tree. It is used and reset in
|
||||
@@ -265,15 +278,6 @@ private:
|
||||
std::string parseSceneTreeElementAndSaveState(QTreeWidgetItem* item, unsigned int level);
|
||||
QString GetCommandParameterList (const G4UIcommand *aCommand);
|
||||
void changeColorAndTransparency(GLuint index, G4Color color);
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
inline void SetQGLContextVisSubThread(QThread *th) {
|
||||
fQGLContextVisSubThread = th;
|
||||
}
|
||||
inline void SetQGLContextMainThread(QThread *th) {
|
||||
fQGLContextMainThread = th;
|
||||
}
|
||||
#endif
|
||||
|
||||
QMenu *fContextMenu;
|
||||
QPoint fLastPos1;
|
||||
@@ -386,12 +390,6 @@ private:
|
||||
#ifdef G4MULTITHREADED
|
||||
QThread* fQGLContextVisSubThread;
|
||||
QThread* fQGLContextMainThread;
|
||||
G4Mutex fmWaitForVisSubThreadQtOpenGLContextMoved;
|
||||
G4Mutex fmWaitForVisSubThreadQtOpenGLContextInitialized;
|
||||
G4Condition fc1_VisSubThreadQtOpenGLContextInitialized;
|
||||
G4Condition fc2_VisSubThreadQtOpenGLContextMoved;
|
||||
G4AutoLock* flWaitForVisSubThreadQtOpenGLContextInitialized;
|
||||
G4AutoLock* flWaitForVisSubThreadQtOpenGLContextMoved;
|
||||
#endif
|
||||
|
||||
public Q_SLOTS :
|
||||
|
||||
@@ -49,7 +49,9 @@ public:
|
||||
const G4String& name = "");
|
||||
~G4OpenGLStoredQtViewer ();
|
||||
void Initialise ();
|
||||
#if QT_VERSION < 0x060000
|
||||
void initializeGL ();
|
||||
#endif
|
||||
void DrawView ();
|
||||
void resizeGL(int width,int height);
|
||||
void paintGL();
|
||||
@@ -78,7 +80,9 @@ protected:
|
||||
G4bool POSelected(size_t POListIndex);
|
||||
G4bool TOSelected(size_t TOListIndex);
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
void showEvent(QShowEvent * event );
|
||||
#endif
|
||||
void wheelEvent(QWheelEvent *event);
|
||||
void mousePressEvent(QMouseEvent *event);
|
||||
void mouseMoveEvent(QMouseEvent *event);
|
||||
|
||||
@@ -54,10 +54,8 @@ public:
|
||||
virtual ~G4OpenGLXViewer ();
|
||||
void SetView ();
|
||||
void ShowView ();
|
||||
#ifdef G4MULTITHREADED
|
||||
void SwitchToVisSubThread();
|
||||
void SwitchToMasterThread();
|
||||
#endif
|
||||
void DrawText(const G4Text&);
|
||||
|
||||
protected:
|
||||
@@ -82,9 +80,7 @@ protected:
|
||||
XSetWindowAttributes swa;
|
||||
GLXDrawable win;
|
||||
GLXContext cxMaster;
|
||||
#ifdef G4MULTITHREADED
|
||||
GLXContext cxVisSubThread;
|
||||
#endif
|
||||
XEvent event;
|
||||
G4int *attributeList,
|
||||
errorBase,
|
||||
|
||||
@@ -33,12 +33,12 @@
|
||||
#include "G4OpenGLImmediateSceneHandler.hh"
|
||||
|
||||
#include "G4ios.hh"
|
||||
#ifdef G4MULTITHREADED
|
||||
#include "G4Threading.hh"
|
||||
#endif
|
||||
#include <qapplication.h>
|
||||
#include <qtabwidget.h>
|
||||
|
||||
#if 0x060000 <= QT_VERSION
|
||||
#include "G4Qt.hh"
|
||||
#endif
|
||||
|
||||
G4OpenGLImmediateQtViewer::G4OpenGLImmediateQtViewer
|
||||
(G4OpenGLImmediateSceneHandler& sceneHandler,
|
||||
@@ -48,6 +48,7 @@ G4OpenGLImmediateQtViewer::G4OpenGLImmediateQtViewer
|
||||
G4OpenGLQtViewer (sceneHandler),
|
||||
G4OpenGLImmediateViewer (sceneHandler)
|
||||
{
|
||||
#if QT_VERSION < 0x060000
|
||||
fQGLWidgetInitialiseCompleted = false;
|
||||
|
||||
setFocusPolicy(Qt::StrongFocus); // enable keybord events
|
||||
@@ -56,19 +57,20 @@ G4OpenGLImmediateQtViewer::G4OpenGLImmediateQtViewer
|
||||
fUpdateGLLock = false;
|
||||
|
||||
if (fViewId < 0) return; // In case error in base class instantiation.
|
||||
#else
|
||||
setFocusPolicy(Qt::StrongFocus); // enable keybord events
|
||||
#endif
|
||||
}
|
||||
|
||||
G4OpenGLImmediateQtViewer::~G4OpenGLImmediateQtViewer() {
|
||||
// makeCurrent(); // Not sure why this - commented out 12-Apr-2021 JA
|
||||
}
|
||||
G4OpenGLImmediateQtViewer::~G4OpenGLImmediateQtViewer() {}
|
||||
|
||||
void G4OpenGLImmediateQtViewer::Initialise() {
|
||||
#if QT_VERSION < 0x060000
|
||||
makeCurrent();
|
||||
|
||||
fQGLWidgetInitialiseCompleted = false;
|
||||
CreateMainWindow (this,QString(GetName()));
|
||||
|
||||
makeCurrent();
|
||||
glDrawBuffer (GL_BACK);
|
||||
|
||||
// set the good tab active
|
||||
@@ -81,16 +83,13 @@ void G4OpenGLImmediateQtViewer::Initialise() {
|
||||
|
||||
fQGLWidgetInitialiseCompleted = true;
|
||||
#else
|
||||
fQGLWidgetInitialiseCompleted = false;
|
||||
CreateMainWindow (this,QString(GetName()));
|
||||
if(G4QGLWidgetType::isValid()) { //G.Barrand: macOS: isValid() needed at startup.
|
||||
makeCurrent();
|
||||
glDrawBuffer (GL_BACK);
|
||||
}
|
||||
fQGLWidgetInitialiseCompleted = true;
|
||||
// Set jpg as default export format for Qt viewer
|
||||
setExportImageFormat("jpg");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
void G4OpenGLImmediateQtViewer::initializeGL () {
|
||||
|
||||
InitializeGLView ();
|
||||
@@ -113,6 +112,7 @@ void G4OpenGLImmediateQtViewer::initializeGL () {
|
||||
// Set jpg as default export format for Qt viewer
|
||||
setExportImageFormat("jpg");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void G4OpenGLImmediateQtViewer::DrawView() {
|
||||
@@ -123,22 +123,20 @@ void G4OpenGLImmediateQtViewer::DrawView() {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef G4MULTITHREADED
|
||||
if (G4Threading::G4GetThreadId() == G4Threading::MASTER_ID) {
|
||||
if (G4Threading::IsMasterThread()) {
|
||||
updateQWidget();
|
||||
}
|
||||
#else
|
||||
updateQWidget();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void G4OpenGLImmediateQtViewer::ComputeView () {
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
makeCurrent();
|
||||
// If a double buffer context has been forced upon us, ignore the
|
||||
// back buffer for this OpenGLImmediate view.
|
||||
// glDrawBuffer (GL_FRONT);
|
||||
#endif
|
||||
|
||||
G4ViewParameters::DrawingStyle dstyle = GetViewParameters().GetDrawingStyle();
|
||||
|
||||
@@ -160,7 +158,9 @@ void G4OpenGLImmediateQtViewer::ComputeView () {
|
||||
savePPMToTemp();
|
||||
}
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
fHasToRepaint = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,10 +173,10 @@ void G4OpenGLImmediateQtViewer::resizeGL(
|
||||
if ((aWidth > 0) && (aHeight > 0)) {
|
||||
#if QT_VERSION < 0x060000
|
||||
ResizeWindow(aWidth,aHeight);
|
||||
fHasToRepaint = sizeHasChanged();
|
||||
#else
|
||||
ResizeWindow(devicePixelRatio()*aWidth,devicePixelRatio()*aHeight);
|
||||
#endif
|
||||
fHasToRepaint = sizeHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,6 +189,7 @@ void G4OpenGLImmediateQtViewer::paintGL()
|
||||
//G.Barrand: don't do any change in the GUI here, just "paint" this widget!
|
||||
#endif
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
if (fPaintEventLock) {
|
||||
// return ;
|
||||
}
|
||||
@@ -200,7 +201,6 @@ void G4OpenGLImmediateQtViewer::paintGL()
|
||||
return;
|
||||
}
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
// DO NOT RESIZE IF SIZE HAS NOT CHANGE
|
||||
if ( !fHasToRepaint) {
|
||||
// L. Garnier : Trap to get the size with mac OSX 10.6 and Qt 4.6(devel)
|
||||
@@ -223,11 +223,14 @@ void G4OpenGLImmediateQtViewer::paintGL()
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
if ((getWinWidth() == 0) && (getWinHeight() == 0)) return; //G.Barrand: needed?
|
||||
#endif
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
#else
|
||||
InitializeGLView ();
|
||||
glDrawBuffer (GL_BACK);
|
||||
#endif
|
||||
|
||||
SetView();
|
||||
@@ -235,9 +238,11 @@ void G4OpenGLImmediateQtViewer::paintGL()
|
||||
ClearView (); //ok, put the background correct
|
||||
ComputeView();
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
fHasToRepaint = false; // could be set to false by ComputeView
|
||||
|
||||
fPaintEventLock = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void G4OpenGLImmediateQtViewer::mousePressEvent(QMouseEvent *event)
|
||||
@@ -260,13 +265,14 @@ void G4OpenGLImmediateQtViewer::wheelEvent (QWheelEvent * event)
|
||||
G4wheelEvent(event);
|
||||
}
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
void G4OpenGLImmediateQtViewer::showEvent (QShowEvent *)
|
||||
{
|
||||
if (fQGLWidgetInitialiseCompleted) {
|
||||
fHasToRepaint = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This function was build in order to make a zoom on double clic event.
|
||||
@@ -313,6 +319,7 @@ void G4OpenGLImmediateQtViewer::paintEvent(QPaintEvent *) {
|
||||
|
||||
|
||||
void G4OpenGLImmediateQtViewer::updateQWidget() {
|
||||
#if QT_VERSION < 0x060000
|
||||
if (fUpdateGLLock) {
|
||||
return;
|
||||
}
|
||||
@@ -323,23 +330,25 @@ void G4OpenGLImmediateQtViewer::updateQWidget() {
|
||||
|
||||
fUpdateGLLock = true;
|
||||
fHasToRepaint= true;
|
||||
#if QT_VERSION < 0x060000
|
||||
repaint();
|
||||
updateViewerPropertiesTableWidget();
|
||||
updateSceneTreeWidget();
|
||||
fUpdateGLLock= false;
|
||||
#else
|
||||
//if (!isCurrentWidget()) return; //G.Barrand: Qt must know if it has to activate paintGL() if the widget is not visible.
|
||||
//G.Barrand: don't do any change in the GUI here, just ask to "paint" this widget!
|
||||
update();
|
||||
#endif
|
||||
fUpdateGLLock= false;
|
||||
}
|
||||
|
||||
|
||||
void G4OpenGLImmediateQtViewer::ShowView (
|
||||
)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
|
||||
void G4OpenGLImmediateQtViewer::ShowView ()
|
||||
{
|
||||
#if QT_VERSION < 0x060000
|
||||
fHasToRepaint = true;
|
||||
activateWindow();
|
||||
#else
|
||||
activateWindow();
|
||||
((QApplication*)G4Qt::getInstance ())->processEvents();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -112,9 +112,6 @@ void G4OpenGLQtViewer::CreateMainWindow (
|
||||
if(fGLWidget) return; //Done.
|
||||
|
||||
fGLWidget = glWidget ;
|
||||
// fGLWidget->makeCurrent();
|
||||
|
||||
G4Qt* interactorManager = G4Qt::getInstance ();
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
ResizeWindow(fVP.GetWindowSizeHintX(),fVP.GetWindowSizeHintY());
|
||||
@@ -144,6 +141,7 @@ void G4OpenGLQtViewer::CreateMainWindow (
|
||||
bool isTabbedView = false;
|
||||
if ( fUiQt) {
|
||||
if (!fBatchMode) {
|
||||
G4Qt* interactorManager = G4Qt::getInstance ();
|
||||
if (!interactorManager->IsExternalApp()) {
|
||||
// INIT size
|
||||
fWinSize_x = fVP.GetWindowSizeHintX();
|
||||
@@ -272,15 +270,6 @@ G4OpenGLQtViewer::G4OpenGLQtViewer (
|
||||
,fLastHighlightName(0)
|
||||
,fIsDeleting(false)
|
||||
{
|
||||
#ifdef G4MULTITHREADED
|
||||
flWaitForVisSubThreadQtOpenGLContextInitialized
|
||||
= new G4AutoLock(fmWaitForVisSubThreadQtOpenGLContextInitialized,
|
||||
std::defer_lock);
|
||||
flWaitForVisSubThreadQtOpenGLContextMoved
|
||||
= new G4AutoLock(fmWaitForVisSubThreadQtOpenGLContextMoved,
|
||||
std::defer_lock);
|
||||
#endif
|
||||
|
||||
// launch Qt if not
|
||||
if (QCoreApplication::instance () == NULL) {
|
||||
fBatchMode = true;
|
||||
@@ -525,12 +514,18 @@ G4OpenGLQtViewer::~G4OpenGLQtViewer (
|
||||
G4cout <<removeTempFolder().toStdString().c_str() <<G4endl; //G.Barrand: with Qt6, it crashes at exit if the viewer is in a detached dialog window.
|
||||
#endif
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
delete flWaitForVisSubThreadQtOpenGLContextInitialized;
|
||||
delete flWaitForVisSubThreadQtOpenGLContextMoved;
|
||||
#endif
|
||||
}
|
||||
|
||||
G4bool G4OpenGLQtViewer::ReadyToDraw() {
|
||||
#if QT_VERSION < 0x060000
|
||||
return true;
|
||||
#else
|
||||
if(!fGLWidget) return false;
|
||||
auto* qGLW = dynamic_cast<G4QGLWidgetType*>(fGLWidget);
|
||||
if (!qGLW) return false;
|
||||
return qGLW->isValid();
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// Create a popup menu for the widget. This menu is activated by right-mouse click
|
||||
@@ -2416,8 +2411,6 @@ QWidget *G4OpenGLQtViewer::getParentWidget()
|
||||
{
|
||||
// launch Qt if not
|
||||
G4Qt* interactorManager = G4Qt::getInstance ();
|
||||
// G4UImanager* UI =
|
||||
// G4UImanager::GetUIpointer();
|
||||
|
||||
bool found = false;
|
||||
QDialog* dialog = NULL;
|
||||
@@ -2815,9 +2808,7 @@ void G4OpenGLQtViewer::DrawText(const G4Text& g4text)
|
||||
|
||||
if (!fGLWidget) return;
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
if (G4Threading::G4GetThreadId() != G4Threading::MASTER_ID) return;
|
||||
#endif
|
||||
if (!G4Threading::IsMasterThread()) return;
|
||||
|
||||
G4VSceneHandler::MarkerSizeType sizeType;
|
||||
G4double size = fSceneHandler.GetMarkerSize(g4text,sizeType);
|
||||
@@ -2833,8 +2824,8 @@ void G4OpenGLQtViewer::DrawText(const G4Text& g4text)
|
||||
const char* textCString = textString.c_str();
|
||||
|
||||
// Calculate move for centre and right adjustment
|
||||
QFontMetrics* f = new QFontMetrics (font);
|
||||
G4double span = f->boundingRect(textCString).width();
|
||||
QFontMetrics f(font);
|
||||
G4double span = f.boundingRect(textCString).width();
|
||||
|
||||
G4double xmove = 0.;
|
||||
G4double ymove = 0.;
|
||||
@@ -4714,10 +4705,10 @@ void G4OpenGLQtViewer::toggleSceneTreeComponentPickingCout(int pickItem) {
|
||||
|
||||
|
||||
void G4OpenGLQtViewer::currentTabActivated(int currentTab) {
|
||||
if (fUiQt->GetViewerTabWidget()->tabText(currentTab) == GetName()) {
|
||||
if (fUiQt->GetViewerTabWidget()->tabText(currentTab) == GetName().data()) {
|
||||
createViewerPropertiesWidget();
|
||||
createPickInfosWidget();
|
||||
createSceneTreeWidget();
|
||||
// createPickInfosWidget(); // Causes a /vis/set/touchable command to do with...
|
||||
// createSceneTreeWidget(); // ...this old scene tree widget (no longer used)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4797,101 +4788,100 @@ QString G4OpenGLQtViewer::GetCommandParameterList (
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
|
||||
namespace {
|
||||
G4Mutex visSubThreadMutex = G4MUTEX_INITIALIZER;
|
||||
G4Condition waitForVisSubThreadInitialized = G4CONDITION_INITIALIZER;
|
||||
G4bool visSubThreadEstablished = false;
|
||||
G4bool qObjectsSwitched = false;
|
||||
G4QGLWidgetType* qGLWidget = nullptr;
|
||||
}
|
||||
|
||||
void G4OpenGLQtViewer::DoneWithMasterThread()
|
||||
{
|
||||
// Called by Main Thread !
|
||||
|
||||
// Useful to avoid two vis thread at the same time
|
||||
//G4MUTEXLOCK(&fmWaitForVisSubThreadQtOpenGLContextInitialized);
|
||||
if(!flWaitForVisSubThreadQtOpenGLContextInitialized->owns_lock())
|
||||
flWaitForVisSubThreadQtOpenGLContextInitialized->lock();
|
||||
// Initialise and check qGLWidget - no need to check in subsequent functions
|
||||
qGLWidget = dynamic_cast<G4QGLWidgetType*>(fGLWidget);
|
||||
if (qGLWidget == nullptr) return;
|
||||
|
||||
// Done with master thread
|
||||
qGLWidget->doneCurrent();
|
||||
|
||||
// Set current QThread for the way back
|
||||
fQGLContextMainThread = QThread::currentThread();
|
||||
}
|
||||
|
||||
void G4OpenGLQtViewer::MovingToVisSubThread()
|
||||
{
|
||||
// Still on master thread but vis thread has been launched
|
||||
|
||||
if (qGLWidget == nullptr) return;
|
||||
|
||||
// Wait until SwitchToVisSubThread has found vis sub-thread QThread
|
||||
{
|
||||
G4AutoLock lock(&visSubThreadMutex);
|
||||
G4CONDITIONWAITLAMBDA(&waitForVisSubThreadInitialized, &lock, []{return visSubThreadEstablished;})
|
||||
}
|
||||
|
||||
// Move stuff to sub-thread
|
||||
if(qGLWidget->context()) qGLWidget->context()->moveToThread(fQGLContextVisSubThread);
|
||||
|
||||
// Inform sub-thread
|
||||
G4AutoLock lock(&visSubThreadMutex);
|
||||
qObjectsSwitched = true;
|
||||
lock.unlock();
|
||||
G4CONDITIONBROADCAST(&waitForVisSubThreadInitialized);
|
||||
}
|
||||
|
||||
void G4OpenGLQtViewer::SwitchToVisSubThread()
|
||||
{
|
||||
// Called by VisSub Thread !
|
||||
|
||||
auto qGLW = dynamic_cast<G4QGLWidgetType*> (fGLWidget) ;
|
||||
if (! qGLW) {
|
||||
return;
|
||||
}
|
||||
if (qGLWidget == nullptr) return;
|
||||
|
||||
// Set the current QThread to its static variable
|
||||
SetQGLContextVisSubThread(QThread::currentThread());
|
||||
fQGLContextVisSubThread = QThread::currentThread();
|
||||
|
||||
// - Wait for the vis thread to set its QThread
|
||||
G4CONDITIONBROADCAST(&fc1_VisSubThreadQtOpenGLContextInitialized);
|
||||
// a condition without a locked mutex is an undefined behavior.
|
||||
// we check if the mutex owns the lock, and if not, we lock it
|
||||
if(!flWaitForVisSubThreadQtOpenGLContextMoved->owns_lock())
|
||||
flWaitForVisSubThreadQtOpenGLContextMoved->lock();
|
||||
// Let MovingToVisSubThread know we have the QThread
|
||||
{
|
||||
G4AutoLock lock(&visSubThreadMutex);
|
||||
visSubThreadEstablished = true;
|
||||
G4CONDITIONBROADCAST(&waitForVisSubThreadInitialized);
|
||||
}
|
||||
|
||||
// Unlock the vis thread if it is Qt Viewer
|
||||
G4CONDITIONWAIT(&fc2_VisSubThreadQtOpenGLContextMoved,
|
||||
flWaitForVisSubThreadQtOpenGLContextMoved);
|
||||
// Wait until MovingToVisSubThread has moved stuff
|
||||
{
|
||||
G4AutoLock lock(&visSubThreadMutex);
|
||||
G4CONDITIONWAITLAMBDA(&waitForVisSubThreadInitialized, &lock, []{return qObjectsSwitched;})
|
||||
}
|
||||
|
||||
// make context current
|
||||
qGLW->makeCurrent();
|
||||
qGLWidget->makeCurrent();
|
||||
}
|
||||
|
||||
void G4OpenGLQtViewer::DoneWithVisSubThread()
|
||||
{
|
||||
// Called by vis sub thread
|
||||
auto qGLW = dynamic_cast<G4QGLWidgetType*> (fGLWidget) ;
|
||||
if (! qGLW) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (qGLWidget == nullptr) return;
|
||||
|
||||
// finish with this vis sub thread context
|
||||
qGLW->doneCurrent();
|
||||
qGLWidget->doneCurrent();
|
||||
|
||||
// and move it back to the main thread
|
||||
qGLW->context()->moveToThread(fQGLContextMainThread);
|
||||
// and move stuff back to the main thread
|
||||
if(qGLWidget->context()) qGLWidget->context()->moveToThread(fQGLContextMainThread);
|
||||
}
|
||||
|
||||
void G4OpenGLQtViewer::SwitchToMasterThread()
|
||||
{
|
||||
// Called by VisSub Thread !
|
||||
// Called by master Thread !
|
||||
|
||||
auto qGLW = dynamic_cast<G4QGLWidgetType*> (fGLWidget) ;
|
||||
if (! qGLW) {
|
||||
return;
|
||||
}
|
||||
if (qGLWidget == nullptr) return;
|
||||
|
||||
// Useful to avoid two vis thread at the same time
|
||||
//G4MUTEXUNLOCK(&fmWaitForVisSubThreadQtOpenGLContextInitialized);
|
||||
if(flWaitForVisSubThreadQtOpenGLContextInitialized->owns_lock())
|
||||
flWaitForVisSubThreadQtOpenGLContextInitialized->unlock();
|
||||
qGLWidget->makeCurrent();
|
||||
|
||||
qGLW->makeCurrent();
|
||||
}
|
||||
|
||||
|
||||
void G4OpenGLQtViewer::MovingToVisSubThread(){
|
||||
// Called by Main Thread !
|
||||
|
||||
auto qGLW = dynamic_cast<G4QGLWidgetType*> (fGLWidget) ;
|
||||
if (! qGLW) {
|
||||
return;
|
||||
}
|
||||
|
||||
// a condition without a locked mutex is an undefined behavior.
|
||||
// we check if the mutex owns the lock, and if not, we lock it
|
||||
if(!flWaitForVisSubThreadQtOpenGLContextInitialized->owns_lock())
|
||||
flWaitForVisSubThreadQtOpenGLContextInitialized->lock();
|
||||
|
||||
// - Wait for the vis sub thread to set its QThread
|
||||
G4CONDITIONWAIT(&fc1_VisSubThreadQtOpenGLContextInitialized,
|
||||
flWaitForVisSubThreadQtOpenGLContextInitialized);
|
||||
|
||||
// Set current QThread for the way back
|
||||
SetQGLContextMainThread(QThread::currentThread());
|
||||
|
||||
// finish with this main thread context
|
||||
qGLW->doneCurrent();
|
||||
qGLW->context()->moveToThread(fQGLContextVisSubThread);
|
||||
|
||||
G4CONDITIONBROADCAST(&fc2_VisSubThreadQtOpenGLContextMoved);
|
||||
visSubThreadEstablished = false;
|
||||
qObjectsSwitched = false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -134,12 +134,17 @@ void G4OpenGLStoredQtSceneHandler::ClearStore () {
|
||||
|
||||
//G4cout << "G4OpenGLStoredQtSceneHandler::ClearStore" << G4endl;
|
||||
|
||||
G4OpenGLStoredSceneHandler::ClearStore (); // Sets need kernel visit, etc.
|
||||
// Should recreate the tree
|
||||
G4OpenGLQtViewer* pGLQtViewer = dynamic_cast<G4OpenGLQtViewer*>(fpViewer);
|
||||
if ( pGLQtViewer ) {
|
||||
pGLQtViewer->clearTreeWidget();
|
||||
}
|
||||
G4OpenGLStoredSceneHandler::ClearStore ();
|
||||
|
||||
// Not needed - the old scene tree is currently (partially) disabled - but
|
||||
// this code somehow affects the view in rare cases, e.g., after twinkling
|
||||
// the volume does not return to its original colour. So I have disabled
|
||||
// this, pending a review of the old scene tree. JA 31/10/24
|
||||
// // Should recreate the tree
|
||||
// G4OpenGLQtViewer* pGLQtViewer = dynamic_cast<G4OpenGLQtViewer*>(fpViewer);
|
||||
// if ( pGLQtViewer ) {
|
||||
// pGLQtViewer->clearTreeWidget();
|
||||
// }
|
||||
}
|
||||
|
||||
void G4OpenGLStoredQtSceneHandler::ClearTransientStore () {
|
||||
|
||||
@@ -33,10 +33,11 @@
|
||||
|
||||
#include "G4OpenGLStoredSceneHandler.hh"
|
||||
#include "G4ios.hh"
|
||||
#ifdef G4MULTITHREADED
|
||||
#include "G4Threading.hh"
|
||||
#endif
|
||||
#include "G4UIQt.hh"
|
||||
#if 0x060000 <= QT_VERSION
|
||||
#include "G4Qt.hh"
|
||||
#endif
|
||||
|
||||
#include <qapplication.h>
|
||||
#include <qtabwidget.h>
|
||||
@@ -52,6 +53,7 @@ G4OpenGLStoredQtViewer::G4OpenGLStoredQtViewer
|
||||
{
|
||||
if (fViewId < 0) return; // In case error in base class instantiation.
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
fQGLWidgetInitialiseCompleted = false;
|
||||
|
||||
// Indicates that the widget has no background, i.e. when the widget receives paint events, the background is not automatically repainted. Note: Unlike WA_OpaquePaintEvent, newly exposed areas are never filled with the background (e.g., after showing a window for the first time the user can see "through" it until the application processes the paint events). This flag is set or cleared by the widget's author.
|
||||
@@ -61,22 +63,23 @@ G4OpenGLStoredQtViewer::G4OpenGLStoredQtViewer
|
||||
fHasToRepaint = false;
|
||||
fPaintEventLock = false;
|
||||
fUpdateGLLock = false;
|
||||
#else
|
||||
// Indicates that the widget has no background, i.e. when the widget receives paint events, the background is not automatically repainted. Note: Unlike WA_OpaquePaintEvent, newly exposed areas are never filled with the background (e.g., after showing a window for the first time the user can see "through" it until the application processes the paint events). This flag is set or cleared by the widget's author.
|
||||
G4QGLWidgetType::setAttribute (Qt::WA_NoSystemBackground);
|
||||
|
||||
setFocusPolicy(Qt::StrongFocus); // enable keybord events
|
||||
#endif
|
||||
}
|
||||
|
||||
G4OpenGLStoredQtViewer::~G4OpenGLStoredQtViewer() {
|
||||
// makeCurrent(); // Not sure why this - commented out 12-Apr-2021 JA
|
||||
// this is connect to the Dialog for deleting it properly
|
||||
// when close event.
|
||||
// ((QDialog*)window())->reject();
|
||||
}
|
||||
G4OpenGLStoredQtViewer::~G4OpenGLStoredQtViewer() {}
|
||||
|
||||
void G4OpenGLStoredQtViewer::Initialise() {
|
||||
#if QT_VERSION < 0x060000
|
||||
makeCurrent();
|
||||
|
||||
fQGLWidgetInitialiseCompleted = false;
|
||||
CreateMainWindow (this,QString(GetName()));
|
||||
|
||||
makeCurrent();
|
||||
glDrawBuffer (GL_BACK);
|
||||
|
||||
// set the good tab active
|
||||
@@ -89,16 +92,13 @@ void G4OpenGLStoredQtViewer::Initialise() {
|
||||
|
||||
fQGLWidgetInitialiseCompleted = true;
|
||||
#else
|
||||
fQGLWidgetInitialiseCompleted = false;
|
||||
CreateMainWindow (this,QString(GetName()));
|
||||
if(G4QGLWidgetType::isValid()) { //G.Barrand: macOS: isValid() needed at startup.
|
||||
makeCurrent();
|
||||
glDrawBuffer (GL_BACK);
|
||||
}
|
||||
fQGLWidgetInitialiseCompleted = true;
|
||||
// Set jpg as default export format for Qt viewer
|
||||
setExportImageFormat("jpg");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
void G4OpenGLStoredQtViewer::initializeGL () {
|
||||
|
||||
InitializeGLView ();
|
||||
@@ -115,6 +115,7 @@ void G4OpenGLStoredQtViewer::initializeGL () {
|
||||
// Set jpg as default export format for Qt viewer
|
||||
setExportImageFormat("jpg");
|
||||
}
|
||||
#endif
|
||||
|
||||
G4bool G4OpenGLStoredQtViewer::CompareForKernelVisit(G4ViewParameters& lastVP)
|
||||
{
|
||||
@@ -228,7 +229,7 @@ void G4OpenGLStoredQtViewer::DrawView () {
|
||||
#if (QT_VERSION < 0x060000) || !defined(G4MULTITHREADED)
|
||||
updateQWidget();
|
||||
#else
|
||||
if (G4Threading::G4GetThreadId() == G4Threading::MASTER_ID) {
|
||||
if (G4Threading::IsMasterThread()) {
|
||||
updateQWidget();
|
||||
} else {
|
||||
update(); //G.Barrand: updateQWidget() induces a crash on run beamOn.
|
||||
@@ -238,7 +239,10 @@ void G4OpenGLStoredQtViewer::DrawView () {
|
||||
|
||||
void G4OpenGLStoredQtViewer::ComputeView () {
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
makeCurrent();
|
||||
#endif
|
||||
|
||||
G4ViewParameters::DrawingStyle dstyle = GetViewParameters().GetDrawingStyle();
|
||||
|
||||
//Make sure current viewer is attached and clean...
|
||||
@@ -296,7 +300,9 @@ void G4OpenGLStoredQtViewer::ComputeView () {
|
||||
savePPMToTemp();
|
||||
}
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
fHasToRepaint = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -311,10 +317,10 @@ void G4OpenGLStoredQtViewer::resizeGL(
|
||||
if ((aWidth > 0) && (aHeight > 0)) {
|
||||
#if QT_VERSION < 0x060000
|
||||
ResizeWindow(aWidth,aHeight);
|
||||
fHasToRepaint = sizeHasChanged();
|
||||
#else
|
||||
ResizeWindow(devicePixelRatio()*aWidth,devicePixelRatio()*aHeight);
|
||||
#endif
|
||||
fHasToRepaint = sizeHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,6 +338,7 @@ void G4OpenGLStoredQtViewer::paintGL()
|
||||
//G.Barrand: don't do any change in the GUI here, just "paint" this widget!
|
||||
#endif
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
if (fPaintEventLock) {
|
||||
// return ;
|
||||
}
|
||||
@@ -345,7 +352,6 @@ void G4OpenGLStoredQtViewer::paintGL()
|
||||
return;
|
||||
}
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
// DO NOT RESIZE IF SIZE HAS NOT CHANGE :
|
||||
// WHEN CLICK ON THE FRAME FOR EXAMPLE
|
||||
// EXECEPT WHEN MOUSE MOVE EVENT
|
||||
@@ -365,6 +371,8 @@ void G4OpenGLStoredQtViewer::paintGL()
|
||||
return;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if ((getWinWidth() == 0) && (getWinHeight() == 0)) return; //G.Barrand: needed?
|
||||
#endif
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
@@ -380,9 +388,11 @@ void G4OpenGLStoredQtViewer::paintGL()
|
||||
ClearView (); //ok, put the background correct
|
||||
ComputeView();
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
fHasToRepaint = false;
|
||||
|
||||
fPaintEventLock = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
@@ -427,12 +437,14 @@ void G4OpenGLStoredQtViewer::wheelEvent (QWheelEvent * event)
|
||||
G4wheelEvent(event);
|
||||
}
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
void G4OpenGLStoredQtViewer::showEvent (QShowEvent *)
|
||||
{
|
||||
if (fQGLWidgetInitialiseCompleted) {
|
||||
fHasToRepaint = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This function was build in order to make a zoom on double clic event.
|
||||
@@ -460,6 +472,7 @@ void G4OpenGLStoredQtViewer::contextMenuEvent(QContextMenuEvent *e)
|
||||
}
|
||||
|
||||
void G4OpenGLStoredQtViewer::updateQWidget() {
|
||||
#if QT_VERSION < 0x060000
|
||||
if (fUpdateGLLock) {
|
||||
return;
|
||||
}
|
||||
@@ -474,34 +487,24 @@ void G4OpenGLStoredQtViewer::updateQWidget() {
|
||||
// The widget's rendering context will become the current context and initializeGL()
|
||||
// will be called if it hasn't already been called.
|
||||
// Copies the back buffer of a double-buffered context to the front buffer.
|
||||
#if QT_VERSION < 0x060000
|
||||
repaint(); // will read scene tree state
|
||||
// updateGL() // From J.Allison picking branch
|
||||
updateViewerPropertiesTableWidget();
|
||||
updateSceneTreeWidget();
|
||||
fUpdateGLLock = false;
|
||||
#else
|
||||
//if (!isCurrentWidget()) return; //G.Barrand: Qt must know if it has to activate paintGL() if the widget is not visible.
|
||||
//G.Barrand: don't do any change in the GUI here, just ask to "paint" this widget!
|
||||
update();
|
||||
#endif
|
||||
fUpdateGLLock = false;
|
||||
}
|
||||
|
||||
void G4OpenGLStoredQtViewer::ShowView (
|
||||
)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
|
||||
void G4OpenGLStoredQtViewer::ShowView ()
|
||||
{
|
||||
// glFlush (); // Tentativley offered by JA 29/04/16.
|
||||
|
||||
// Some X servers fail to draw all trajectories, particularly Mac
|
||||
// XQuartz. Revisit this at a future date. Meanwhile, issue an
|
||||
// extra...
|
||||
// ClearView(); // Necessary? JA 29/04/16
|
||||
// DrawView(); // Necessary? JA 29/04/16
|
||||
activateWindow();
|
||||
// glFlush(); // NO NEED and as drawView will already cause a flush
|
||||
// that could do a double flush
|
||||
|
||||
#if 0x060000 <= QT_VERSION
|
||||
((QApplication*)G4Qt::getInstance ())->processEvents();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -89,24 +89,15 @@ extern "C" {
|
||||
}
|
||||
|
||||
void G4OpenGLXViewer::SetView () {
|
||||
#ifdef G4MULTITHREADED
|
||||
if (G4Threading::IsMasterThread()) {
|
||||
glXMakeCurrent (dpy, win, cxMaster);
|
||||
} else {
|
||||
glXMakeCurrent (dpy, win, cxVisSubThread);
|
||||
}
|
||||
#else
|
||||
glXMakeCurrent (dpy, win, cxMaster);
|
||||
#endif
|
||||
G4OpenGLViewer::SetView ();
|
||||
}
|
||||
|
||||
void G4OpenGLXViewer::ShowView () {
|
||||
#ifdef G4MULTITHREADED
|
||||
// G4int thread_id = G4Threading::G4GetThreadId();
|
||||
// G4cout << "G4OpenGLXViewer::ShowView: thread " << thread_id << G4endl;
|
||||
#endif
|
||||
|
||||
// glXWaitGL (); //Wait for effects of all previous OpenGL commands to
|
||||
//be propagated before progressing.
|
||||
// JA: Commented out July 2021 - slows rendering down in some cases and I
|
||||
@@ -131,24 +122,22 @@ void G4OpenGLXViewer::ShowView () {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
|
||||
void G4OpenGLXViewer::SwitchToVisSubThread()
|
||||
{
|
||||
// G4cout << "G4OpenGLXViewer::SwitchToVisSubThread" << G4endl;
|
||||
#ifdef G4MULTITHREADED
|
||||
cxVisSubThread = glXCreateContext (dpy, vi, cxMaster, true);
|
||||
glXMakeCurrent (dpy, win, cxVisSubThread);
|
||||
#endif
|
||||
}
|
||||
|
||||
void G4OpenGLXViewer::SwitchToMasterThread()
|
||||
{
|
||||
// G4cout << "G4OpenGLXViewer::SwitchToMasterThread" << G4endl;
|
||||
#ifdef G4MULTITHREADED
|
||||
glXMakeCurrent (dpy, win, cxMaster);
|
||||
// and destroy sub-thread context
|
||||
glXDestroyContext (dpy, cxVisSubThread);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void G4OpenGLXViewer::GetXConnection () {
|
||||
// get a connection.
|
||||
|
||||
@@ -6,6 +6,18 @@ It must **not** be used as a substitute for writing good git commit messages!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## 2024-08-14 John Allison (visQt3D-V11-02-03)
|
||||
- G4Qt3DViewer:
|
||||
- Resolve the timing issues around switching to the vis sub-thread with the
|
||||
use of G4CONDITIONWAITLAMBDA.
|
||||
|
||||
## 2024-07-12 Guy Barrand (visQt3D-V11-02-02)
|
||||
- G4Qt3DViewer: implement a resizeEvent() method to avoid a bad aspect ratio at viewer creation.
|
||||
- G4Qt3DSceneHandler: in AddPrimitive(G4Polyline), stay with the Qt5 code. The one for Qt6 using
|
||||
Qt3DCore::QGeometryView is crashy.
|
||||
- G4Qt3DViewer: in MovingToVisSubThread(), SwitchToMasterThread() protect against nullptr for p1, p2.
|
||||
It permits to avoid crash in case of doing /run/beamOn in vis.mac at startup.
|
||||
|
||||
## 2024-05-23 Guy Barrand (visQt3D-V11-02-01)
|
||||
- G4Qt3DSceneHandler::EstablishG4Qt3DQEntities(): have a missing:
|
||||
fpPhysicalVolumeObjects.clear();
|
||||
|
||||
@@ -53,6 +53,7 @@ public:
|
||||
void SwitchToMasterThread();
|
||||
|
||||
protected:
|
||||
virtual void resizeEvent(QResizeEvent*);
|
||||
|
||||
void KernelVisitDecision ();
|
||||
G4bool CompareForKernelVisit(G4ViewParameters&);
|
||||
|
||||
@@ -361,19 +361,10 @@ void G4Qt3DSceneHandler::AddPrimitive(const G4Polyline& polyline)
|
||||
polylineEntity->addComponent(material);
|
||||
|
||||
auto renderer = new Qt3DRender::QGeometryRenderer;
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
|
||||
auto geometryView = new Qt3DCore::QGeometryView(polylineGeometry);
|
||||
geometryView->setObjectName("polylineGeometryView");
|
||||
geometryView->setGeometry(polylineGeometry);
|
||||
geometryView->setVertexCount((G4int)(2*nLines));
|
||||
geometryView->setPrimitiveType(Qt3DCore::QGeometryView::Lines);
|
||||
renderer->setView(geometryView);
|
||||
#else
|
||||
renderer->setObjectName("polylineRenderer");
|
||||
renderer->setGeometry(polylineGeometry);
|
||||
renderer->setVertexCount(2*(G4int)nLines);
|
||||
renderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Lines);
|
||||
#endif
|
||||
polylineEntity->addComponent(renderer);
|
||||
}
|
||||
|
||||
|
||||
@@ -63,9 +63,6 @@ void G4Qt3DViewer::Initialise()
|
||||
return;
|
||||
}
|
||||
fUIWidget = QWidget::createWindowContainer(this);
|
||||
fUIWidget->setMinimumSize(QSize(200, 100));
|
||||
fUIWidget->setMaximumSize(screen()->size());
|
||||
// fUIWidget->setFocusPolicy(Qt::NoFocus); //??
|
||||
uiQt->AddTabWidget(fUIWidget,QString(fName));
|
||||
|
||||
setRootEntity(fQt3DSceneHandler.fpQt3DScene);
|
||||
@@ -76,6 +73,10 @@ G4Qt3DViewer::~G4Qt3DViewer()
|
||||
setRootEntity(nullptr);
|
||||
}
|
||||
|
||||
void G4Qt3DViewer::resizeEvent(QResizeEvent*) {
|
||||
SetView();
|
||||
}
|
||||
|
||||
void G4Qt3DViewer::SetView()
|
||||
{
|
||||
// Background colour
|
||||
@@ -158,77 +159,123 @@ void G4Qt3DViewer::DrawView()
|
||||
|
||||
void G4Qt3DViewer::ShowView()
|
||||
{
|
||||
#if QT_VERSION < 0x060000
|
||||
// show() may only be called from master thread
|
||||
if (G4Threading::IsMasterThread()) {
|
||||
show();
|
||||
}
|
||||
// The way Qt seems to work, we don't seem to need a show() anyway, but
|
||||
// we'll leave it in - it seems not to have any effect, good or bad.
|
||||
#endif
|
||||
}
|
||||
|
||||
void G4Qt3DViewer::FinishView()
|
||||
{
|
||||
#if QT_VERSION < 0x060000
|
||||
if (G4Threading::IsMasterThread()) {
|
||||
show();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Note: the order of calling of MovingToVisSubThread and SwitchToVisSubThread
|
||||
// is undefined. The order of calling is
|
||||
// DoneWithMasterThread
|
||||
// MovingToVisSubThread ) or ( SwitchToVisSubThread
|
||||
// SwitchToVisSubThread ) ( MovingToVisSubThread
|
||||
// DoneWithVisSubThread
|
||||
// MovingToMasterThread
|
||||
// SwitchToMasterThread
|
||||
// So regarding the move/switch to the vis sub-thread, we have to employ mutex locks and conditions.
|
||||
// If the viewer wishes to accept drawing from the vis sub-thread, Qt3D has to moveToThread.
|
||||
// But at this point we are still on the master thread and the value of the sub-thread's QThread is
|
||||
// not known. So it has to wait - a conditional wait, conditional on establishment of the sub-thread
|
||||
// and the provision of a pointer to the QThread version of the vis sub-thread. In turn, the
|
||||
// sub-thread has to wait until the QObjects have been moved to the sub-thread.
|
||||
|
||||
namespace {
|
||||
QThread* masterQThread = nullptr;
|
||||
QThread* visSubThreadQThread = nullptr;
|
||||
|
||||
G4Mutex visSubThreadMutex = G4MUTEX_INITIALIZER;
|
||||
G4Condition waitForVisSubThreadInitialized = G4CONDITION_INITIALIZER;
|
||||
G4bool visSubThreadEstablished = false;
|
||||
G4bool qObjectsSwitched = false;
|
||||
}
|
||||
|
||||
# include <chrono>
|
||||
|
||||
void G4Qt3DViewer::MovingToVisSubThread()
|
||||
// Still on master thread but vis thread has been launched
|
||||
{
|
||||
#ifdef G4QT3DDEBUG
|
||||
G4cout << "G4Qt3DViewer::MovingToVisSubThread" << G4endl;
|
||||
#endif
|
||||
// Still on master thread but vis thread has been launched
|
||||
// Make note of master QThread
|
||||
masterQThread = QThread::currentThread();
|
||||
|
||||
// Wait until SwitchToVisSubThread has found vis sub-thread QThread
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
{
|
||||
G4AutoLock lock(&visSubThreadMutex);
|
||||
G4CONDITIONWAITLAMBDA(&waitForVisSubThreadInitialized, &lock, []{return visSubThreadEstablished;})
|
||||
}
|
||||
|
||||
// Move relevant stuff to vis sub-thread QThread
|
||||
auto p1 = fQt3DSceneHandler.fpQt3DScene->parent();
|
||||
auto p2 = p1->parent();
|
||||
p2->moveToThread(visSubThreadQThread);
|
||||
if(p1) {
|
||||
auto p2 = p1->parent();
|
||||
if(p2) {
|
||||
p2->moveToThread(visSubThreadQThread);
|
||||
} else {
|
||||
p1->moveToThread(visSubThreadQThread);
|
||||
}
|
||||
}
|
||||
|
||||
// Inform sub-thread
|
||||
G4AutoLock lock(&visSubThreadMutex);
|
||||
qObjectsSwitched = true;
|
||||
lock.unlock();
|
||||
G4CONDITIONBROADCAST(&waitForVisSubThreadInitialized);
|
||||
}
|
||||
|
||||
void G4Qt3DViewer::SwitchToVisSubThread()
|
||||
// On vis sub-thread before any drawing
|
||||
{
|
||||
#ifdef G4QT3DDEBUG
|
||||
G4cout << "G4Qt3DViewer::SwitchToVisSubThread" << G4endl;
|
||||
#endif
|
||||
// On vis sub-thread before any drawing
|
||||
// Make note of vis-subthread QThread for MovingToVisSubThread
|
||||
visSubThreadQThread = QThread::currentThread();
|
||||
// Wait until SwitchToVisSubThread has moved stuff
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
|
||||
// Let MovingToVisSubThread know we have the QThread
|
||||
{
|
||||
G4AutoLock lock(&visSubThreadMutex);
|
||||
visSubThreadEstablished = true;
|
||||
G4CONDITIONBROADCAST(&waitForVisSubThreadInitialized);
|
||||
}
|
||||
|
||||
// Wait until MovingToVisSubThread has moved stuff
|
||||
{
|
||||
G4AutoLock lock(&visSubThreadMutex);
|
||||
G4CONDITIONWAITLAMBDA(&waitForVisSubThreadInitialized, &lock, []{return qObjectsSwitched;})
|
||||
}
|
||||
}
|
||||
|
||||
void G4Qt3DViewer::MovingToMasterThread()
|
||||
// On vis sub-thread just before exit
|
||||
{
|
||||
#ifdef G4QT3DDEBUG
|
||||
G4cout << "G4Qt3DViewer::MovingToMasterThread" << G4endl;
|
||||
#endif
|
||||
// On vis sub-thread just before exit
|
||||
// Move relevant stuff to master QThread.
|
||||
auto p1 = fQt3DSceneHandler.fpQt3DScene->parent();
|
||||
auto p2 = p1->parent();
|
||||
p2->moveToThread(masterQThread);
|
||||
// Zero - will be different next run
|
||||
if(p1) {
|
||||
auto p2 = p1->parent();
|
||||
if(p2) {
|
||||
p2->moveToThread(masterQThread);
|
||||
} else {
|
||||
p1->moveToThread(masterQThread);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset
|
||||
visSubThreadQThread = nullptr;
|
||||
qObjectsSwitched = false;
|
||||
}
|
||||
|
||||
void G4Qt3DViewer::SwitchToMasterThread()
|
||||
// On master thread after vis sub-thread has terminated
|
||||
{
|
||||
#ifdef G4QT3DDEBUG
|
||||
G4cout << "G4Qt3DViewer::SwitchToMasterThread" << G4endl;
|
||||
#endif
|
||||
// On master thread after vis sub-thread has terminated
|
||||
// Nothing to do
|
||||
visSubThreadEstablished = false;
|
||||
}
|
||||
|
||||
void G4Qt3DViewer::KernelVisitDecision () {
|
||||
|
||||
@@ -6,6 +6,9 @@ It must **not** be used as a substitute for writing good git commit messages!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## 2024-06-21 Ben Morgan (vis_toolssg-V1-02-02)
|
||||
- Use runtime checks for MT mode.
|
||||
|
||||
## 2024-04-30 Ben Morgan (vis_toolssg-V11-02-01)
|
||||
- Replace TOOLSSG vis driver variables that are just synonyms for more
|
||||
fundamental config options (e.g. GEANT4_USE_QT) with the underlying
|
||||
|
||||
@@ -296,7 +296,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
virtual void SwitchToVisSubThread() {}
|
||||
|
||||
virtual void SwitchToMasterThread() {
|
||||
@@ -321,7 +320,6 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//SG_VIEWER* sg_viewer() {return fSGViewer;}
|
||||
protected:
|
||||
|
||||
@@ -123,9 +123,7 @@ tools::sg::separator* G4ToolsSGSceneHandler::GetOrCreateNode()
|
||||
{ // Retrieve or create a G4ToolsSGNode node suitable for next solid or primitive
|
||||
|
||||
// For time being, avoid errors in MT mode - see G4ToolsSGViewer::SwitchToMasterThread
|
||||
#ifdef G4MULTITHREADED
|
||||
if (!G4Threading::IsMasterThread()) return nullptr;
|
||||
#endif
|
||||
|
||||
if (fReadyForTransients) { // All transients hang from this node
|
||||
tools::sg::separator* sep = new tools::sg::separator;
|
||||
|
||||
@@ -6,6 +6,25 @@ It must **not** be used as a substitute for writing good git commit messages!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## 2024-10-17 John Allison (visVtk-V11-02-07)
|
||||
- G4VtkMessenger.cc:
|
||||
- Added x3d to /vis/vtk/export format parameter guidance.
|
||||
- Set parameter omitables to false.
|
||||
|
||||
## 2024-10-07 Stewart Boogert (visVtk-V11-02-06)
|
||||
- G4VtkViewer:
|
||||
- Added export for X3D file format
|
||||
|
||||
## 2024-08-13 John Allison (visVtk-V11-02-05)
|
||||
- G4VtkQtViewer:
|
||||
- Resolve the timing issues around switching to the vis sub-thread with the
|
||||
use of G4CONDITIONWAITLAMBDA.
|
||||
|
||||
## 2024-07-12 Guy Barrand (visVtk-V11-02-04)
|
||||
- G4VtkQtViewer: in DoneWithVisSubThread(), SwitchToMasterThread() protect against a
|
||||
possible null qGLW->context(). It permits to avoid a crash in case of doing /run/beamOn
|
||||
in vis.mac at startup.
|
||||
|
||||
## 2024-05-27 Guy Barrand (visVtk-V11-02-03)
|
||||
- G4VtxQtViewer: MT: have the variables mWaitForVisSubThreadQtOpenGLContextMoved,
|
||||
mWaitForVisSubThreadQtOpenGLContextInitialized,
|
||||
|
||||
@@ -59,7 +59,17 @@ class G4VtkQtViewer : public QVTKOpenGLNativeWidget, public G4VtkViewer
|
||||
void Initialise() override;
|
||||
virtual void CreateMainWindow(QVTKOpenGLNativeWidget*, const QString&);
|
||||
#ifdef G4MULTITHREADED
|
||||
// In MT mode these functions are called in the following order for each run:
|
||||
// For switching threads in MT mode
|
||||
// Note: the order of calling of MovingToVisSubThread and SwitchToVisSubThread
|
||||
// is undefined, so we have to use mutexes to ensure required information,
|
||||
// namely the vis sub-thread address, is available before moving objects.
|
||||
// To summarise, the order of calling is
|
||||
// DoneWithMasterThread
|
||||
// MovingToVisSubThread ) or ( SwitchToVisSubThread
|
||||
// SwitchToVisSubThread ) ( MovingToVisSubThread
|
||||
// DoneWithVisSubThread
|
||||
// MovingToMasterThread
|
||||
// SwitchToMasterThread
|
||||
// Called on the master thread before starting the vis sub-thread.
|
||||
void DoneWithMasterThread() override;
|
||||
// Called on the master thread after starting the vis sub-thread.
|
||||
@@ -69,12 +79,9 @@ class G4VtkQtViewer : public QVTKOpenGLNativeWidget, public G4VtkViewer
|
||||
// Called on the vis sub-thread when all events have been processed.
|
||||
void DoneWithVisSubThread() override;
|
||||
// Called on the vis sub-thread when all events have been processed.
|
||||
// virtual void MovingToMasterThread (); Not used in G4OpenGLQtViewer.
|
||||
// virtual void MovingToMasterThread (); Not used in G4VtkQtViewer.
|
||||
// Called on the master thread after the vis sub-thread has terminated.
|
||||
void SwitchToMasterThread() override;
|
||||
|
||||
inline void SetQGLContextVisSubThread(QThread* th) { fQGLContextVisSubThread = th; }
|
||||
inline void SetQGLContextMainThread(QThread* th) { fQGLContextMainThread = th; }
|
||||
#endif
|
||||
|
||||
void FinishView() override;
|
||||
@@ -103,14 +110,8 @@ class G4VtkQtViewer : public QVTKOpenGLNativeWidget, public G4VtkViewer
|
||||
QWidget* fGLWidget;
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
QThread* fQGLContextVisSubThread;
|
||||
QThread* fQGLContextMainThread;
|
||||
G4Mutex fmWaitForVisSubThreadQtOpenGLContextMoved;
|
||||
G4Mutex fmWaitForVisSubThreadQtOpenGLContextInitialized;
|
||||
G4Condition fc1_VisSubThreadQtOpenGLContextInitialized;
|
||||
G4Condition fc2_VisSubThreadQtOpenGLContextMoved;
|
||||
G4AutoLock* flWaitForVisSubThreadQtOpenGLContextInitialized;
|
||||
G4AutoLock* flWaitForVisSubThreadQtOpenGLContextMoved;
|
||||
QThread* fQVtkContextVisSubThread;
|
||||
QThread* fQVtkContextMainThread;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -229,6 +229,7 @@ class G4VtkViewer : public G4VViewer
|
||||
void ExportVRMLScene(G4String);
|
||||
void ExportVTPScene(G4String);
|
||||
void ExportGLTFScene(G4String);
|
||||
void ExportX3DScene(G4String);
|
||||
void ExportJSONRenderWindowScene(G4String);
|
||||
void ExportVTPCutter(G4String fileName);
|
||||
void ExportFormatStore(G4String fileName, G4String store);
|
||||
|
||||
@@ -62,12 +62,12 @@ G4VtkMessenger::G4VtkMessenger()
|
||||
fpCommandExport->SetGuidance("Export a screenshot or OBJ file of current Vtk viewer");
|
||||
|
||||
// File type for export
|
||||
auto parameterExport = new G4UIparameter("format", 's', omitable = true);
|
||||
fpCommandExport->SetGuidance("File type (jpg,tiff,eps,ps,obj,vtp,gltf,vrml)");
|
||||
auto parameterExport = new G4UIparameter("format", 's', omitable = false);
|
||||
fpCommandExport->SetGuidance("File type (jpg,tiff,eps,ps,obj,vtp,gltf,vrml,x3d)");
|
||||
fpCommandExport->SetParameter(parameterExport);
|
||||
|
||||
// File name for export
|
||||
parameterExport = new G4UIparameter("file-name", 's', omitable = true);
|
||||
parameterExport = new G4UIparameter("file-name", 's', omitable = false);
|
||||
fpCommandExport->SetGuidance("File name");
|
||||
fpCommandExport->SetParameter(parameterExport);
|
||||
|
||||
@@ -332,6 +332,8 @@ void G4VtkMessenger::SetNewValue(G4UIcommand* command, G4String newValue)
|
||||
pVtkViewer->ExportVTPScene(name);
|
||||
else if (format == "gltf")
|
||||
pVtkViewer->ExportGLTFScene(name);
|
||||
else if (format == "x3d")
|
||||
pVtkViewer->ExportX3DScene(name);
|
||||
else
|
||||
G4cout << "Unknown /vis/vtk/export file format" << G4endl;
|
||||
}
|
||||
|
||||
@@ -58,22 +58,12 @@
|
||||
G4VtkQtViewer::G4VtkQtViewer(G4VSceneHandler& sceneHandler, const G4String& name)
|
||||
: G4VtkViewer(sceneHandler, name)
|
||||
{
|
||||
#ifdef G4MULTITHREADED
|
||||
flWaitForVisSubThreadQtOpenGLContextInitialized =
|
||||
new G4AutoLock(fmWaitForVisSubThreadQtOpenGLContextInitialized, std::defer_lock);
|
||||
flWaitForVisSubThreadQtOpenGLContextMoved =
|
||||
new G4AutoLock(fmWaitForVisSubThreadQtOpenGLContextMoved, std::defer_lock);
|
||||
#endif
|
||||
G4Qt::getInstance();
|
||||
//this->setFormat(QVTKOpenGLNativeWidget::defaultFormat());
|
||||
}
|
||||
|
||||
G4VtkQtViewer::~G4VtkQtViewer()
|
||||
{
|
||||
#ifdef G4MULTITHREADED
|
||||
delete flWaitForVisSubThreadQtOpenGLContextInitialized;
|
||||
delete flWaitForVisSubThreadQtOpenGLContextMoved;
|
||||
#endif
|
||||
}
|
||||
|
||||
void G4VtkQtViewer::Initialise()
|
||||
@@ -113,100 +103,101 @@ void G4VtkQtViewer::CreateMainWindow(QVTKOpenGLNativeWidget* vtkWidget, const QS
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
|
||||
namespace {
|
||||
G4Mutex visSubThreadMutex = G4MUTEX_INITIALIZER;
|
||||
G4Condition waitForVisSubThreadInitialized = G4CONDITION_INITIALIZER;
|
||||
G4bool visSubThreadEstablished = false;
|
||||
G4bool qObjectsSwitched = false;
|
||||
QVTKOpenGLNativeWidget* qVtkW = nullptr;
|
||||
}
|
||||
|
||||
void G4VtkQtViewer::DoneWithMasterThread()
|
||||
{
|
||||
// Called by Main Thread !
|
||||
|
||||
// Useful to avoid two vis thread at the same time
|
||||
// G4MUTEXLOCK(&fmWaitForVisSubThreadQtOpenGLContextInitialized);
|
||||
if (!flWaitForVisSubThreadQtOpenGLContextInitialized->owns_lock())
|
||||
flWaitForVisSubThreadQtOpenGLContextInitialized->lock();
|
||||
// Initialise and check qVtkW - no need to check in subsequent functions
|
||||
qVtkW = dynamic_cast<QVTKOpenGLNativeWidget*>(fGLWidget);
|
||||
if (qVtkW == nullptr) return;
|
||||
|
||||
// Done with master thread
|
||||
qVtkW->doneCurrent();
|
||||
|
||||
// Set current QThread for the way back
|
||||
fQVtkContextMainThread = QThread::currentThread();
|
||||
}
|
||||
|
||||
void G4VtkQtViewer::MovingToVisSubThread()
|
||||
{
|
||||
// Still on master thread but vis thread has been launched
|
||||
|
||||
if (qVtkW == nullptr) return;
|
||||
|
||||
// Wait until SwitchToVisSubThread has found vis sub-thread QThread
|
||||
{
|
||||
G4AutoLock lock(&visSubThreadMutex);
|
||||
G4CONDITIONWAITLAMBDA(&waitForVisSubThreadInitialized, &lock, []{return visSubThreadEstablished;})
|
||||
}
|
||||
|
||||
// Move stuff to sub-thread
|
||||
if(qVtkW->context()) qVtkW->context()->moveToThread(fQVtkContextVisSubThread);
|
||||
|
||||
// Inform sub-thread
|
||||
G4AutoLock lock(&visSubThreadMutex);
|
||||
qObjectsSwitched = true;
|
||||
lock.unlock();
|
||||
G4CONDITIONBROADCAST(&waitForVisSubThreadInitialized);
|
||||
}
|
||||
|
||||
void G4VtkQtViewer::SwitchToVisSubThread()
|
||||
{
|
||||
// Called by VisSub Thread !
|
||||
|
||||
auto qGLW = dynamic_cast<QVTKOpenGLNativeWidget*>(fGLWidget);
|
||||
if (qGLW == nullptr) {
|
||||
return;
|
||||
if (qVtkW == nullptr) return;
|
||||
|
||||
fQVtkContextVisSubThread = QThread::currentThread();
|
||||
|
||||
// Let MovingToVisSubThread know we have the QThread
|
||||
{
|
||||
G4AutoLock lock(&visSubThreadMutex);
|
||||
visSubThreadEstablished = true;
|
||||
G4CONDITIONBROADCAST(&waitForVisSubThreadInitialized);
|
||||
}
|
||||
|
||||
// Set the current QThread to its static variable
|
||||
SetQGLContextVisSubThread(QThread::currentThread());
|
||||
|
||||
// - Wait for the vis thread to set its QThread
|
||||
G4CONDITIONBROADCAST(&fc1_VisSubThreadQtOpenGLContextInitialized);
|
||||
// a condition without a locked mutex is an undefined behavior.
|
||||
// we check if the mutex owns the lock, and if not, we lock it
|
||||
if (!flWaitForVisSubThreadQtOpenGLContextMoved->owns_lock())
|
||||
flWaitForVisSubThreadQtOpenGLContextMoved->lock();
|
||||
|
||||
// Unlock the vis thread if it is Qt Viewer
|
||||
G4CONDITIONWAIT(&fc2_VisSubThreadQtOpenGLContextMoved, flWaitForVisSubThreadQtOpenGLContextMoved);
|
||||
// Wait until MovingToVisSubThread has moved stuff
|
||||
{
|
||||
G4AutoLock lock(&visSubThreadMutex);
|
||||
G4CONDITIONWAITLAMBDA(&waitForVisSubThreadInitialized, &lock, []{return qObjectsSwitched;})
|
||||
}
|
||||
|
||||
// make context current
|
||||
qGLW->makeCurrent();
|
||||
qVtkW->makeCurrent();
|
||||
}
|
||||
|
||||
void G4VtkQtViewer::DoneWithVisSubThread()
|
||||
{
|
||||
// Called by vis sub thread
|
||||
auto qGLW = dynamic_cast<QVTKOpenGLNativeWidget*>(fGLWidget);
|
||||
if (qGLW == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (qVtkW == nullptr) return;
|
||||
|
||||
// finish with this vis sub thread context
|
||||
qGLW->doneCurrent();
|
||||
qVtkW->doneCurrent();
|
||||
|
||||
// and move it back to the main thread
|
||||
qGLW->context()->moveToThread(fQGLContextMainThread);
|
||||
if(qVtkW->context()) qVtkW->context()->moveToThread(fQVtkContextMainThread);
|
||||
}
|
||||
|
||||
void G4VtkQtViewer::SwitchToMasterThread()
|
||||
{
|
||||
// Called by VisSub Thread !
|
||||
|
||||
auto qGLW = dynamic_cast<QVTKOpenGLNativeWidget*>(fGLWidget);
|
||||
if (qGLW == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (qVtkW == nullptr) return;
|
||||
|
||||
// Useful to avoid two vis thread at the same time
|
||||
// G4MUTEXUNLOCK(&fmWaitForVisSubThreadQtOpenGLContextInitialized);
|
||||
if (flWaitForVisSubThreadQtOpenGLContextInitialized->owns_lock())
|
||||
flWaitForVisSubThreadQtOpenGLContextInitialized->unlock();
|
||||
qVtkW->makeCurrent();
|
||||
|
||||
qGLW->makeCurrent();
|
||||
visSubThreadEstablished = false;
|
||||
qObjectsSwitched = false;
|
||||
}
|
||||
|
||||
void G4VtkQtViewer::MovingToVisSubThread()
|
||||
{
|
||||
// Called by Main Thread !
|
||||
|
||||
auto qGLW = dynamic_cast<QVTKOpenGLNativeWidget*>(fGLWidget);
|
||||
if (qGLW == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
// a condition without a locked mutex is an undefined behavior.
|
||||
// we check if the mutex owns the lock, and if not, we lock it
|
||||
if (!flWaitForVisSubThreadQtOpenGLContextInitialized->owns_lock())
|
||||
flWaitForVisSubThreadQtOpenGLContextInitialized->lock();
|
||||
|
||||
// - Wait for the vis sub thread to set its QThread
|
||||
G4CONDITIONWAIT(&fc1_VisSubThreadQtOpenGLContextInitialized,
|
||||
flWaitForVisSubThreadQtOpenGLContextInitialized);
|
||||
|
||||
// Set current QThread for the way back
|
||||
SetQGLContextMainThread(QThread::currentThread());
|
||||
|
||||
// finish with this main thread context
|
||||
qGLW->doneCurrent();
|
||||
qGLW->context()->moveToThread(fQGLContextVisSubThread);
|
||||
G4CONDITIONBROADCAST(&fc2_VisSubThreadQtOpenGLContextMoved);
|
||||
}
|
||||
#endif
|
||||
|
||||
void G4VtkQtViewer::FinishView()
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
#include <vtkOBJImporter.h>
|
||||
#include <vtkGLTFExporter.h>
|
||||
#include <vtkOOGLExporter.h>
|
||||
#include <vtkX3DExporter.h>
|
||||
#include <vtkJSONRenderWindowExporter.h>
|
||||
#include <vtkVtkJSSceneGraphSerializer.h>
|
||||
//#include <vtkBufferedArchiver.h>
|
||||
@@ -417,6 +418,14 @@ void G4VtkViewer::ExportGLTFScene(G4String fileName) {
|
||||
exporter->Write();
|
||||
}
|
||||
|
||||
void G4VtkViewer::ExportX3DScene(G4String fileName) {
|
||||
vtkSmartPointer<vtkX3DExporter> exporter = vtkSmartPointer<vtkX3DExporter>::New();
|
||||
exporter->SetRenderWindow(_renderWindow);
|
||||
exporter->SetFileName((fileName+".x3d").c_str());
|
||||
exporter->Write();
|
||||
}
|
||||
|
||||
|
||||
void G4VtkViewer::ExportJSONRenderWindowScene(G4String /*fileName*/) {
|
||||
vtkSmartPointer<vtkJSONRenderWindowExporter> exporter = vtkSmartPointer<vtkJSONRenderWindowExporter>::New();
|
||||
vtkSmartPointer<vtkVtkJSSceneGraphSerializer> serializer = vtkSmartPointer<vtkVtkJSSceneGraphSerializer>::New();
|
||||
|
||||
@@ -6,6 +6,15 @@ It must **not** be used as a substitute for writing good git commit messages!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## 2024-09-29 John Allison (gMocren-V11-02-02)
|
||||
- More Coverity fixes
|
||||
|
||||
## 2024-08-31 John Allison (gMocren-V11-02-01)
|
||||
- More Coverity fixes
|
||||
|
||||
## 2024-07-17 John Allison (gMocren-V11-02-00)
|
||||
- Coverity fixes
|
||||
|
||||
## 2023-02-06 Ben Morgan (gMocren-V11-01-00)
|
||||
- Isolate private headers and update dependencies
|
||||
|
||||
|
||||
@@ -90,6 +90,8 @@
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
|
||||
#include <utility>
|
||||
|
||||
//----- constants
|
||||
const char GDD_FILE_HEADER [] = "g4_";
|
||||
const char DEFAULT_GDD_FILE_NAME[] = "g4_00.gdd";
|
||||
@@ -1713,7 +1715,7 @@ void G4GMocrenFileSceneHandler::AddCompound( const G4VHit & hit) {
|
||||
} else {
|
||||
std::map<Index3D, G4double> hits;
|
||||
hits.insert(std::map<Index3D, G4double>::value_type(id, value));
|
||||
kNestedHitsList[hitNames[i]] = hits;
|
||||
kNestedHitsList[hitNames[i]] = std::move(hits);
|
||||
}
|
||||
|
||||
|
||||
@@ -1775,7 +1777,7 @@ void G4GMocrenFileSceneHandler::AddCompound(const G4THitsMap<G4double> & hits) {
|
||||
} else {
|
||||
std::map<Index3D, G4double> hit;
|
||||
hit.insert(std::map<Index3D, G4double>::value_type(id, *(itr->second)));
|
||||
kNestedHitsList[scorername] = hit;
|
||||
kNestedHitsList[scorername] = std::move(hit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1847,7 +1849,7 @@ void G4GMocrenFileSceneHandler::AddCompound(const G4THitsMap<G4StatDouble> & hit
|
||||
} else {
|
||||
std::map<Index3D, G4double> hit;
|
||||
hit.insert(std::map<Index3D, G4double>::value_type(id, itr->second->sum_wx()));
|
||||
kNestedHitsList[scorername] = hit;
|
||||
kNestedHitsList[scorername] = std::move(hit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
#include "G4UIcommand.hh"
|
||||
#include "G4Tokenizer.hh"
|
||||
|
||||
#include <utility>
|
||||
|
||||
G4GMocrenMessenger::G4GMocrenMessenger()
|
||||
: suffix (""), geometry(true), pointAttributes(false), solids(true), invisibles(true),
|
||||
kgMocrenVolumeName("gMocrenVolume"),
|
||||
@@ -198,7 +200,7 @@ G4String G4GMocrenMessenger::GetCurrentValue(G4UIcommand * command) {
|
||||
|
||||
void G4GMocrenMessenger::SetNewValue(G4UIcommand * command, G4String newValue) {
|
||||
if (command==setEventNumberSuffixCommand) {
|
||||
suffix = newValue;
|
||||
suffix = std::move(newValue);
|
||||
} else if (command==appendGeometryCommand) {
|
||||
geometry = appendGeometryCommand->GetNewBoolValue(newValue);
|
||||
} else if (command==addPointAttributesCommand) {
|
||||
@@ -208,15 +210,15 @@ void G4GMocrenMessenger::SetNewValue(G4UIcommand * command, G4String newValue) {
|
||||
// } else if (command==writeInvisiblesCommand) {
|
||||
// invisibles = writeInvisiblesCommand->GetNewBoolValue(newValue);
|
||||
} else if (command == kSetgMocrenVolumeNameCommand) {
|
||||
kgMocrenVolumeName = newValue;
|
||||
kgMocrenVolumeName = std::move(newValue);
|
||||
} else if (command == kAddgMocrenHitNameCommand) {
|
||||
kgMocrenHitNames.push_back(newValue);
|
||||
kgMocrenHitNames.push_back(std::move(newValue));
|
||||
} else if (command == kResetgMocrenHitNameCommand) {
|
||||
kgMocrenHitNames.clear();
|
||||
} else if (command == kSetgMocrenScoringMeshNameCommand) {
|
||||
kgMocrenScoringMeshName = newValue;
|
||||
kgMocrenScoringMeshName = std::move(newValue);
|
||||
} else if (command == kAddgMocrenHitScorerNameCommand) {
|
||||
kgMocrenHitScorerNames.push_back(newValue);
|
||||
kgMocrenHitScorerNames.push_back(std::move(newValue));
|
||||
} else if (command == kResetgMocrenHitScorerNameCommand) {
|
||||
kgMocrenHitScorerNames.clear();
|
||||
} else if (command == kListgMocrenCommand) {
|
||||
|
||||
@@ -6,6 +6,140 @@ It must **not** be used as a substitute for writing good git commit messages!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## 2024-10-27 John Allison (visman-V11-02-28)
|
||||
- G4VisExecutive.icc:
|
||||
- Remove #include <QtGlobal> - no longer needed.
|
||||
- Was included to resolve some Qt5/6 issues in 11.2.
|
||||
|
||||
## 2024-10-16 John Allison (visman-V11-02-27)
|
||||
- G4VSceneHandler.cc:
|
||||
- Move some printing outside the loop over models - more hygenic
|
||||
- Improve indentation.
|
||||
|
||||
## 2024-10-03 John Allison (visman-V11-02-26)
|
||||
- Introduce TOOLS_USE_FREETYPE flag in vis management for /vis/plot command
|
||||
- sources.cmake:
|
||||
- Add geant4_module_compile_definitions.
|
||||
- Set cpp flag TOOLS_USE_FREETYPE if built with GEANT4_USE_FREETYPE.
|
||||
- G4VisCommandsCompound.cc:
|
||||
- If TOOLS_USE_FREETYPE, augment /vis/plot command to take "style" argument.
|
||||
- Candidates are: "none ROOT_default hippodraw".
|
||||
- Default is: "ROOT_default".
|
||||
|
||||
## 2024-10-02 John Allison (visman-V11-02-25)
|
||||
- G4VisManager.cc:
|
||||
- Protect KeepForPostProcessing() with an mtVisSubThreadMutex lock.
|
||||
- KeepForPostProcessing() is called on a worker thread, PostProcessingFinished()
|
||||
is called on the vis sub-thread, so should be protected.
|
||||
- Not sure about sub-event parallelism, because KeepForPostProcessing() is still
|
||||
called on a worker thread, but PostProcessingFinished() is called from the
|
||||
G4SubEvtRunManager. But having a short piece of code locked does no harm, so
|
||||
let's do this.
|
||||
- G4VisManager.cc, G4VisCommandsSceneAdd.cc:
|
||||
- Tidied redundant comments and corrected some.
|
||||
|
||||
## 2024-09-30 Makoto Asai (visman-V11-02-24)
|
||||
- G4VisManager.cc, G4VisCommandsSceneAdd.cc:
|
||||
- Optimize the timing of G4Event::KeepForPostProcessing() and
|
||||
G4Event::PostProcessingFinished() so that event object that are not
|
||||
requested to be kept are cleanly deleted at the end of each run.
|
||||
Kept events are deleted at the beginning of the next run or when the
|
||||
program terminates.
|
||||
- Use G4Run::GetNumberOfKeptEvent() to properly display the number of kept
|
||||
events.
|
||||
- Co-working with run-V11-02-18
|
||||
|
||||
## 2024-09-12 John Allison (visman-V11-02-23)
|
||||
- G4ViewParameters.cc: Minor improvements to messages in output operator<<.
|
||||
- G4VisCommandsSceneAdd.cc:
|
||||
- G4VisCommandSceneAddLogo::SetNewValue (/vis/scene/add/logo):
|
||||
- Ensure the logo respects the current requested number of sides per circle.
|
||||
- G4VisCommandsViewer.cc:
|
||||
- G4VisCommandViewerCreate::SetNewValue (/vis/viewer/create):
|
||||
- Simplify the use of view parameters of a pre-existing viewer.
|
||||
- Use the parameters of the most recent viewer whatever its type.
|
||||
- Exclude GlobalMarkerScale from parameters copied from pre-existing viewer.
|
||||
- Thus each viewer is allowed to specify its own GlobalMarkerScale.
|
||||
- Mostly viewers use the default value of 1, but ToolsSG sets it to 2
|
||||
to handle special displays such as Apple's Retina.
|
||||
|
||||
## 2024-08-31 John Allison (visman-V11-02-22)
|
||||
- Coverity fixes.
|
||||
- Some checks, which gave Coverity concern, are no longer needed, because
|
||||
Begin/EndOfRun/Event are protected by flag set once and for all in
|
||||
BeginOfRun.
|
||||
|
||||
## 2024-08-26 John Allison (visman-V11-02-21)
|
||||
- G4VisManager.cc:
|
||||
- Protect Begin/EndOfRun against invalid view (includes check on
|
||||
existence of a scene).
|
||||
- A dead-lock in MT mode if there is a view but no scene with OGL.
|
||||
- Seems viewer has trouble changing threads.
|
||||
- Some tidying and streamlining.
|
||||
- Introduced local booleans isValidViewForRun and isFakeRun.
|
||||
|
||||
## 2024-08-18 John Allison (visman-V11-02-20)
|
||||
- Improve messaging around /vis/verbose and /vis/list.
|
||||
- G4VisManager:
|
||||
- Introduce PrintAvailableVerbosity().
|
||||
- GetVerbosityValue: Print verbosity options on unknown or empty argument
|
||||
- G4VisCommands.cc:
|
||||
- /vis/list: Add printing of verbosity options.
|
||||
- /vis/verbose: Change default value to empty string (triggers printing
|
||||
of verbosity options in G4VisManager::GetVerbosityValue().
|
||||
|
||||
## 2024-08-04 John Allison (visman-V11-02-19)
|
||||
- Fix "accumulate" bug in Serial mode, and other small improvements.
|
||||
- G4VisManager.cc:
|
||||
- Bug fix: In Serial mode, "accumulate" fails (behaves like "refresh").
|
||||
- This relates to end-of-event action, e.g., trajectory drawing.
|
||||
- Bug was introduced in visman-V11-02-18.
|
||||
- Fix and rationalise by moving the following to EndOfEventCleanup():
|
||||
if (pScene->GetRefreshAtEndOfEvent()) {
|
||||
pViewer->ShowView();
|
||||
pSceneHandler->SetMarkForClearingTransientStore(true);
|
||||
}
|
||||
- Improve printing of colours in PrintAvailableColours and advise on use.
|
||||
- Used in /vis/list.
|
||||
- Tidy further:
|
||||
- Remove some commented-out debug printing to make code cleaner to read.
|
||||
- Fix some errant indentations.
|
||||
- G4VisCommandsSceneAdd.cc:
|
||||
- Move date model (/vis/scene/add/date) from run-duration to end-of-event list.
|
||||
- Thus date and time are updated for every event displayed.
|
||||
|
||||
## 2024-07-21 John Allison (visman-V11-02-18)
|
||||
- G4VisManager: Further rationalising and tidying after visman-V11-02-12.
|
||||
- Replace method `G4bool Relinquishable` (used only if false) by its logical
|
||||
opposite, `G4bool RequiredToBeKeptForVis` - clearer.
|
||||
- Move `void EventReadyForVis` (invoked by G4SubEvtRunManager) to improve
|
||||
readability of code.
|
||||
- Improve some messaging.
|
||||
|
||||
## 2024-07-21 John Allison (visman-V11-02-17)
|
||||
- G4VisExecutive.icc:
|
||||
- Remove duplicate instantiation of TOOLSSG_OFFSCREEN
|
||||
|
||||
## 2024-07-17 John Allison (visman-V11-02-16)
|
||||
- With gMocren-V11-02-00, modeling-V11-02-02
|
||||
- Coverity fixes
|
||||
|
||||
## 2024-07-12 Guy Barrand (visman-V11-02-15)
|
||||
- G4VViewer.hh: add virtual ReadyToDraw(). It helps avoiding a crash on macOS
|
||||
if doing /run/beamOn in vis.mac at startup.
|
||||
- G4VSceneHandler.cc: DrawEvent(), DrawEndOfRunModels(): check if viewer is
|
||||
ReadyToDraw() at begin of method.
|
||||
|
||||
## 2024-07-06 John Allison (visman-V11-02-14)
|
||||
- G4VisManager:
|
||||
- Call PostProcessingFinished for _every_ event in EndOfEventCleanup.
|
||||
- Write lengthy comment about different end-of-event scenarios.
|
||||
- Tidy up previous tag visman-V11-02-12.
|
||||
|
||||
## 2024-06-21 Ben Morgan (visman-V11-02-13)
|
||||
- Remove use of G4MULTITHREADED symbol where not required, using runtime checks
|
||||
as far as possible.
|
||||
|
||||
## 2024-06-04 John Allison (visman-V11-02-12)
|
||||
- G4VisManager:
|
||||
- Implement EventReadyForVis, used by G4SubEvtRunManager.
|
||||
|
||||
@@ -105,9 +105,10 @@ public: // With description
|
||||
// It is not yet the end of all drawing; that is signalled by
|
||||
// ShowView ().)
|
||||
|
||||
virtual G4bool ReadyToDraw() {return true;}
|
||||
|
||||
std::vector<G4ThreeVector> ComputeFlyThrough(G4Vector3D*);
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
// Note: the order of calling of MovingToVisSubThread and SwitchToVisSubThread
|
||||
// is undefined, so you may need to implement mutexes to ensure your preferred
|
||||
// order - see, e.g., G4OpenGLQtViewer. To summarise, the order of calling is
|
||||
@@ -120,23 +121,22 @@ public: // With description
|
||||
// SwitchToMasterThread
|
||||
|
||||
// Called on the master thread before starting the vis sub-thread.
|
||||
virtual void DoneWithMasterThread ();
|
||||
virtual void DoneWithMasterThread () {}
|
||||
|
||||
// Called on the master thread after starting the vis sub-thread.
|
||||
virtual void MovingToVisSubThread ();
|
||||
virtual void MovingToVisSubThread () {}
|
||||
|
||||
// Called on the vis sub-thread at start of vis sub-thread.
|
||||
virtual void SwitchToVisSubThread ();
|
||||
virtual void SwitchToVisSubThread () {}
|
||||
|
||||
// Called on the vis sub-thread when all events have been processed.
|
||||
virtual void DoneWithVisSubThread ();
|
||||
virtual void DoneWithVisSubThread () {}
|
||||
|
||||
// Called on the vis sub-thread when all events have been processed.
|
||||
virtual void MovingToMasterThread ();
|
||||
virtual void MovingToMasterThread () {}
|
||||
|
||||
// Called on the master thread after the vis sub-thread has terminated.
|
||||
virtual void SwitchToMasterThread ();
|
||||
#endif
|
||||
virtual void SwitchToMasterThread () {}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Stuff for scene tree.
|
||||
|
||||
@@ -70,10 +70,10 @@ protected:
|
||||
|
||||
void InterpolateViews
|
||||
(G4VViewer* currentViewer,
|
||||
std::vector<G4ViewParameters> viewVector,
|
||||
const std::vector<G4ViewParameters>& viewVector,
|
||||
const G4int nInterpolationPoints = 50,
|
||||
const G4int waitTimePerPointmilliseconds = 20,
|
||||
const G4String exportString = "");
|
||||
const G4String& exportString = "");
|
||||
|
||||
void InterpolateToNewView
|
||||
(G4VViewer* currentViewer,
|
||||
@@ -81,7 +81,7 @@ protected:
|
||||
const G4ViewParameters& newVP,
|
||||
const G4int nInterpolationPoints = 50,
|
||||
const G4int waitTimePerPointmilliseconds = 20,
|
||||
const G4String exportString = "");
|
||||
const G4String& exportString = "");
|
||||
|
||||
void Twinkle
|
||||
// Twinkles the touchables in paths
|
||||
|
||||
@@ -186,7 +186,7 @@ private:
|
||||
|
||||
class G4VVisCommandGeometrySet: public G4VVisCommandGeometry {
|
||||
protected:
|
||||
void Set(G4String logVolName, const G4VVisCommandGeometrySetFunction&,
|
||||
void Set(const G4String& logVolName, const G4VVisCommandGeometrySetFunction&,
|
||||
G4int requestedDepth);
|
||||
void SetLVVisAtts(G4LogicalVolume*, const G4VVisCommandGeometrySetFunction&,
|
||||
G4int depth, G4int requestedDepth);
|
||||
|
||||
@@ -27,8 +27,6 @@
|
||||
|
||||
// /vis/multithreading commands - John Allison 29th September 2015
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
|
||||
#ifndef G4VISCOMMANDSMULTITHREADING_HH
|
||||
#define G4VISCOMMANDSMULTITHREADING_HH
|
||||
|
||||
@@ -66,5 +64,3 @@ private:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -138,10 +138,6 @@
|
||||
#include "G4VtkQt.hh" // no_geant4_module_check
|
||||
#endif
|
||||
|
||||
#if defined (G4VIS_USE_OPENGLQT) || (G4VIS_USE_TOOLSSG_QT_GLES)
|
||||
#include <QtGlobal>
|
||||
#endif
|
||||
|
||||
#include "G4UImanager.hh"
|
||||
#include "G4UIsession.hh"
|
||||
#include "G4UIbatch.hh"
|
||||
@@ -346,7 +342,6 @@ void G4VisExecutive::RegisterGraphicsSystems () {
|
||||
RegisterGraphicsSystem (new G4RayTracer);
|
||||
RegisterGraphicsSystem (new G4VRML2File);
|
||||
RegisterGraphicsSystem (new G4GMocrenFile);
|
||||
RegisterGraphicsSystem (new G4ToolsSGOffscreen);
|
||||
G4VGraphicsSystem* tsg_offscreen = new G4ToolsSGOffscreen;
|
||||
RegisterGraphicsSystem(tsg_offscreen);
|
||||
tsg_offscreen->AddNickname("TSG_FILE");
|
||||
|
||||
@@ -333,8 +333,6 @@ public: // With description
|
||||
G4bool FilterHit(const G4VHit&);
|
||||
G4bool FilterDigi(const G4VDigi&);
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
|
||||
virtual void SetUpForAThread();
|
||||
// This method is invoked by G4WorkerRunManager
|
||||
|
||||
@@ -345,7 +343,6 @@ public: // With description
|
||||
static G4ThreadFunReturnType G4VisSubThread(G4ThreadFunArgType);
|
||||
// Vis sub-thread function.
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Administration routines.
|
||||
@@ -363,14 +360,10 @@ private:
|
||||
void BeginOfEvent ();
|
||||
|
||||
void EndOfEvent ();
|
||||
// This is called on change of state (G4ApplicationState). It is
|
||||
// used to draw hits, digis and trajectories if included in the
|
||||
// current scene at the end of event, as required.
|
||||
G4bool Relinquishable (G4int eventID, G4int nKeptEvents, G4int nRequests);
|
||||
void EndOfEventKernel (const G4Event* event);
|
||||
void EndOfEventCleanup
|
||||
(const G4Event* currentEvent,
|
||||
G4int eventID); // See EndOfEventKernel: can be == -2?
|
||||
void EndOfEventKernel (const G4Event* currentEvent);
|
||||
void EndOfEventCleanup (const G4Event* currentEvent);
|
||||
G4bool RequiredToBeKeptForVis (G4int eventID);
|
||||
// Cluster of methods to handle end of event.
|
||||
|
||||
void EndOfRun ();
|
||||
|
||||
@@ -419,10 +412,8 @@ public: // With description
|
||||
G4bool GetReviewingPlots () const;
|
||||
G4bool GetAbortReviewPlots () const;
|
||||
const G4ViewParameters& GetDefaultViewParameters () const;
|
||||
#ifdef G4MULTITHREADED
|
||||
G4int GetMaxEventQueueSize () const;
|
||||
G4bool GetWaitOnEventQueueFull () const;
|
||||
#endif
|
||||
virtual const G4String& GetDefaultGraphicsSystemName();
|
||||
// The above has to be virtual so that the derived class, G4VisExecutive,
|
||||
// can override and non-const because on first pass it may/should
|
||||
@@ -452,10 +443,8 @@ public: // With description
|
||||
void SetReviewingPlots (G4bool);
|
||||
void SetAbortReviewPlots (G4bool);
|
||||
void SetDefaultViewParameters (const G4ViewParameters&);
|
||||
#ifdef G4MULTITHREADED
|
||||
void SetMaxEventQueueSize (G4int);
|
||||
void SetWaitOnEventQueueFull (G4bool);
|
||||
#endif
|
||||
void SetDefaultGraphicsSystemName(const G4String&);
|
||||
void SetDefaultXGeometryString (const G4String&);
|
||||
void SetDefaultGraphicsSystemBasis(const G4String&);
|
||||
@@ -485,6 +474,8 @@ public: // With description
|
||||
static std::vector<G4String> VerbosityGuidanceStrings;
|
||||
// Guidance on the use of visualization verbosity.
|
||||
|
||||
static void PrintAvailableVerbosity (std::ostream& os);
|
||||
|
||||
void PrintAvailableGraphicsSystems (Verbosity, std::ostream& = G4cout) const;
|
||||
|
||||
protected:
|
||||
@@ -564,10 +555,8 @@ private:
|
||||
G4bool fIsDrawGroup;
|
||||
G4int fDrawGroupNestingDepth;
|
||||
G4bool fIgnoreStateChanges;
|
||||
#ifdef G4MULTITHREADED
|
||||
G4int fMaxEventQueueSize;
|
||||
G4bool fWaitOnEventQueueFull;
|
||||
#endif
|
||||
|
||||
// Trajectory draw model manager
|
||||
G4VisModelManager<G4VTrajectoryModel>* fpTrajDrawModelMgr;
|
||||
|
||||
@@ -126,8 +126,6 @@ inline const G4ViewParameters& G4VisManager::GetDefaultViewParameters() const {
|
||||
return fDefaultViewParameters;
|
||||
}
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
|
||||
inline G4int G4VisManager::GetMaxEventQueueSize() const {
|
||||
return fMaxEventQueueSize;
|
||||
}
|
||||
@@ -136,8 +134,6 @@ inline G4bool G4VisManager::GetWaitOnEventQueueFull () const {
|
||||
return fWaitOnEventQueueFull;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline const G4String& G4VisManager::GetDefaultGraphicsSystemName () {
|
||||
return fDefaultGraphicsSystemName;
|
||||
}
|
||||
@@ -212,8 +208,6 @@ inline void G4VisManager::SetDefaultViewParameters
|
||||
fDefaultViewParameters = vp;
|
||||
}
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
|
||||
inline void G4VisManager::SetMaxEventQueueSize (G4int size) {
|
||||
fMaxEventQueueSize = size;
|
||||
}
|
||||
@@ -222,8 +216,6 @@ inline void G4VisManager::SetWaitOnEventQueueFull (G4bool wait) {
|
||||
fWaitOnEventQueueFull = wait;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline void G4VisManager::SetDefaultGraphicsSystemName (const G4String& name) {
|
||||
fDefaultGraphicsSystemName = name;
|
||||
}
|
||||
|
||||
@@ -102,3 +102,7 @@ geant4_module_link_libraries(G4vis_management
|
||||
if(GEANT4_BUILD_MULTITHREADED)
|
||||
geant4_module_link_libraries(G4vis_management PRIVATE G4volumes)
|
||||
endif()
|
||||
|
||||
if(GEANT4_USE_FREETYPE)
|
||||
geant4_module_compile_definitions(G4vis_management PRIVATE TOOLS_USE_FREETYPE)
|
||||
endif()
|
||||
|
||||
@@ -754,39 +754,39 @@ void G4VSceneHandler::ProcessScene()
|
||||
}
|
||||
}
|
||||
|
||||
// Some printing
|
||||
if(verbosity >= G4VisManager::confirmations) {
|
||||
for (const auto& model: runDurationModelList) {
|
||||
if (model.fActive) {
|
||||
auto pvModel = dynamic_cast<G4PhysicalVolumeModel*>(model.fpModel);
|
||||
if (pvModel) {
|
||||
G4int nTouchables = 0;
|
||||
G4cout << "Numbers of touchables by depth in model \""
|
||||
<< pvModel->GetGlobalDescription() << "\":";
|
||||
for (const auto& dn : pvModel->GetNumberOfTouchables()) {
|
||||
G4cout << "\n Depth " << dn.first << ": " << dn.second;
|
||||
nTouchables += dn.second;
|
||||
}
|
||||
G4cout << "\n Total number of touchables: " << nTouchables << G4endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fProblematicVolumes.size() > 0) {
|
||||
G4cout << "Problematic volumes:";
|
||||
for (const auto& prob: fProblematicVolumes) {
|
||||
G4cout << "\n " << prob.first->GetName() << " (" << prob.second << ')';
|
||||
}
|
||||
G4cout << G4endl;
|
||||
}
|
||||
}
|
||||
|
||||
fpModel = 0;
|
||||
delete pMP;
|
||||
|
||||
EndModeling();
|
||||
}
|
||||
|
||||
// Some printing
|
||||
if(verbosity >= G4VisManager::confirmations) {
|
||||
for (const auto& model: runDurationModelList) {
|
||||
if (model.fActive) {
|
||||
auto pvModel = dynamic_cast<G4PhysicalVolumeModel*>(model.fpModel);
|
||||
if (pvModel) {
|
||||
G4int nTouchables = 0;
|
||||
G4cout << "Numbers of touchables by depth in model \""
|
||||
<< pvModel->GetGlobalDescription() << "\":";
|
||||
for (const auto& dn : pvModel->GetNumberOfTouchables()) {
|
||||
G4cout << "\n Depth " << dn.first << ": " << dn.second;
|
||||
nTouchables += dn.second;
|
||||
}
|
||||
G4cout << "\n Total number of touchables: " << nTouchables << G4endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fProblematicVolumes.size() > 0) {
|
||||
G4cout << "Problematic volumes:";
|
||||
for (const auto& prob: fProblematicVolumes) {
|
||||
G4cout << "\n " << prob.first->GetName() << " (" << prob.second << ')';
|
||||
}
|
||||
G4cout << G4endl;
|
||||
}
|
||||
}
|
||||
|
||||
fReadyForTransients = true;
|
||||
|
||||
// Refresh event from end-of-event model list.
|
||||
@@ -869,6 +869,7 @@ void G4VSceneHandler::ProcessScene()
|
||||
|
||||
void G4VSceneHandler::DrawEvent(const G4Event* event)
|
||||
{
|
||||
if(!fpViewer->ReadyToDraw()) return;
|
||||
const std::vector<G4Scene::Model>& EOEModelList =
|
||||
fpScene -> GetEndOfEventModelList ();
|
||||
std::size_t nModels = EOEModelList.size();
|
||||
@@ -887,7 +888,7 @@ void G4VSceneHandler::DrawEvent(const G4Event* event)
|
||||
fpViewer->InsertModelInSceneTree(fpModel);
|
||||
|
||||
// Reset modeling parameters pointer
|
||||
fpModel -> SetModelingParameters(0);
|
||||
fpModel -> SetModelingParameters(0);
|
||||
}
|
||||
}
|
||||
fpModel = 0;
|
||||
@@ -897,6 +898,7 @@ void G4VSceneHandler::DrawEvent(const G4Event* event)
|
||||
|
||||
void G4VSceneHandler::DrawEndOfRunModels()
|
||||
{
|
||||
if(!fpViewer->ReadyToDraw()) return;
|
||||
const std::vector<G4Scene::Model>& EORModelList =
|
||||
fpScene -> GetEndOfRunModelList ();
|
||||
std::size_t nModels = EORModelList.size();
|
||||
@@ -909,7 +911,7 @@ void G4VSceneHandler::DrawEndOfRunModels()
|
||||
fpModel -> SetModelingParameters(pMP);
|
||||
|
||||
// Describe to the current scene handler
|
||||
fpModel -> DescribeYourselfTo (*this);
|
||||
fpModel -> DescribeYourselfTo (*this);
|
||||
|
||||
// Enter models in the scene tree
|
||||
fpViewer->InsertModelInSceneTree(fpModel);
|
||||
|
||||
@@ -234,8 +234,8 @@ void G4VViewer::UpdateGUISceneTree()
|
||||
|
||||
void G4VViewer::InsertModelInSceneTree(G4VModel* model)
|
||||
{
|
||||
auto modelType = model->GetType();
|
||||
auto modelDescription = model->GetGlobalDescription();
|
||||
const auto& modelType = model->GetType();
|
||||
const auto& modelDescription = model->GetGlobalDescription();
|
||||
|
||||
auto type = G4SceneTreeItem::model;
|
||||
auto pvModel = dynamic_cast<G4PhysicalVolumeModel*>(model);
|
||||
@@ -443,40 +443,6 @@ std::list<G4SceneTreeItem>::iterator G4VViewer::SceneTreeScene::FindOrInsertTouc
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
|
||||
void G4VViewer::DoneWithMasterThread()
|
||||
{
|
||||
// G4cout << "G4VViewer::DoneWithMasterThread" << G4endl;
|
||||
}
|
||||
|
||||
void G4VViewer::MovingToMasterThread()
|
||||
{
|
||||
// G4cout << "G4VViewer::MovingToMasterThread" << G4endl;
|
||||
}
|
||||
|
||||
void G4VViewer::SwitchToVisSubThread()
|
||||
{
|
||||
// G4cout << "G4VViewer::SwitchToVisSubThread" << G4endl;
|
||||
}
|
||||
|
||||
void G4VViewer::DoneWithVisSubThread()
|
||||
{
|
||||
// G4cout << "G4VViewer::DoneWithVisSubThread" << G4endl;
|
||||
}
|
||||
|
||||
void G4VViewer::MovingToVisSubThread()
|
||||
{
|
||||
// G4cout << "G4VViewer::MovingToVisSubThread" << G4endl;
|
||||
}
|
||||
|
||||
void G4VViewer::SwitchToMasterThread()
|
||||
{
|
||||
// G4cout << "G4VViewer::SwitchToMasterThread" << G4endl;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const G4VViewer& v)
|
||||
{
|
||||
os << "View " << v.fName << ":\n";
|
||||
|
||||
@@ -293,10 +293,10 @@ void G4VVisCommand::RefreshIfRequired(G4VViewer* viewer) {
|
||||
|
||||
void G4VVisCommand::InterpolateViews
|
||||
(G4VViewer* currentViewer,
|
||||
std::vector<G4ViewParameters> viewVector,
|
||||
const std::vector<G4ViewParameters>& viewVector,
|
||||
const G4int nInterpolationPoints,
|
||||
const G4int waitTimePerPointmilliseconds,
|
||||
const G4String exportString)
|
||||
const G4String& exportString)
|
||||
{
|
||||
const G4int safety = (G4int)viewVector.size()*nInterpolationPoints;
|
||||
G4int safetyCount = 0;
|
||||
@@ -322,7 +322,7 @@ void G4VVisCommand::InterpolateToNewView
|
||||
const G4ViewParameters& newVP,
|
||||
const G4int nInterpolationPoints,
|
||||
const G4int waitTimePerPointmilliseconds,
|
||||
const G4String exportString)
|
||||
const G4String& exportString)
|
||||
{
|
||||
std::vector<G4ViewParameters> viewVector;
|
||||
viewVector.push_back(oldVP);
|
||||
|
||||
@@ -1011,7 +1011,7 @@ std::ostream& operator << (std::ostream& os, const G4ViewParameters& v) {
|
||||
|
||||
os << "\n Default TextVisAttributes:\n " << v.fDefaultTextVisAttributes;
|
||||
|
||||
os << "\n Default marker: " << v.fDefaultMarker;
|
||||
os << "\n Default marker:\n " << v.fDefaultMarker;
|
||||
|
||||
os << "\n Global marker scale: " << v.fGlobalMarkerScale;
|
||||
|
||||
@@ -1048,7 +1048,7 @@ std::ostream& operator << (std::ostream& os, const G4ViewParameters& v) {
|
||||
default: os << "unrecognised"; break;
|
||||
}
|
||||
|
||||
os << "\n Vis attributes modifiers: ";
|
||||
os << "\nVis attributes modifiers: ";
|
||||
const std::vector<G4ModelingParameters::VisAttributesModifier>& vams =
|
||||
v.fVisAttributesModifiers;
|
||||
if (vams.empty()) {
|
||||
@@ -1057,7 +1057,7 @@ std::ostream& operator << (std::ostream& os, const G4ViewParameters& v) {
|
||||
os << vams;
|
||||
}
|
||||
|
||||
os << "\n Time window parameters:"
|
||||
os << "\nTime window parameters:"
|
||||
<< "\n Start time: " << v.fStartTime/ns << " ns"
|
||||
<< "\n End time: " << v.fEndTime/ns << " ns"
|
||||
<< "\n Fade factor: " << v.fFadeFactor;
|
||||
@@ -1083,7 +1083,7 @@ std::ostream& operator << (std::ostream& os, const G4ViewParameters& v) {
|
||||
<< ' ' << v.fDisplayLightFrontGreen << ' ' << v.fDisplayLightFrontBlue;
|
||||
}
|
||||
|
||||
os << "\n Special Mesh Rendering";
|
||||
os << "\nSpecial Mesh Rendering";
|
||||
if (v.fSpecialMeshRendering) {
|
||||
os << " requested with option \"" << v.fSpecialMeshRenderingOption;
|
||||
os << "\" for ";
|
||||
|
||||
@@ -214,10 +214,10 @@ G4String G4VisCommandList::GetCurrentValue (G4UIcommand*)
|
||||
|
||||
void G4VisCommandList::SetNewValue (G4UIcommand*, G4String newValue)
|
||||
{
|
||||
G4String& verbosityString = newValue;
|
||||
G4VisManager::Verbosity verbosity =
|
||||
fpVisManager->GetVerbosityValue(verbosityString);
|
||||
G4VisManager::Verbosity verbosity = fpVisManager->GetVerbosityValue(newValue);
|
||||
|
||||
G4VisManager::PrintAvailableVerbosity(G4cout);
|
||||
G4cout << G4endl;
|
||||
fpVisManager->PrintAvailableGraphicsSystems(verbosity);
|
||||
G4cout << G4endl;
|
||||
fpVisManager->PrintAvailableModels(verbosity);
|
||||
@@ -228,6 +228,7 @@ void G4VisCommandList::SetNewValue (G4UIcommand*, G4String newValue)
|
||||
G4cout << G4endl;
|
||||
G4UImanager* UImanager = G4UImanager::GetUIpointer();
|
||||
UImanager->ApplyCommand("/vis/scene/list ! " + newValue);
|
||||
G4cout << G4endl;
|
||||
UImanager->ApplyCommand("/vis/viewer/list ! " + newValue);
|
||||
|
||||
G4cout <<
|
||||
@@ -563,7 +564,7 @@ G4VisCommandVerbose::G4VisCommandVerbose () {
|
||||
fpCommand -> SetGuidance(G4VisManager::VerbosityGuidanceStrings[i]);
|
||||
}
|
||||
fpCommand -> SetParameterName("verbosity", omitable=true);
|
||||
fpCommand -> SetDefaultValue("warnings");
|
||||
fpCommand -> SetDefaultValue("");
|
||||
}
|
||||
|
||||
G4VisCommandVerbose::~G4VisCommandVerbose () {
|
||||
@@ -580,6 +581,6 @@ void G4VisCommandVerbose::SetNewValue (G4UIcommand*,
|
||||
fpVisManager->GetVerbosityValue(newValue);
|
||||
fpVisManager->SetVerboseLevel(verbosity);
|
||||
// Always prints whatever the verbosity...
|
||||
G4cout << "Visualization verbosity changed to "
|
||||
G4cout << "Visualization verbosity is now "
|
||||
<< G4VisManager::VerbosityString(verbosity) << G4endl;
|
||||
}
|
||||
|
||||
@@ -414,6 +414,12 @@ G4VisCommandPlot::G4VisCommandPlot ()
|
||||
fpCommand -> SetParameter (parameter);
|
||||
parameter = new G4UIparameter ("id", 'i', omitable = false);
|
||||
fpCommand -> SetParameter (parameter);
|
||||
#ifdef TOOLS_USE_FREETYPE
|
||||
parameter = new G4UIparameter ("style", 's', omitable = true);
|
||||
parameter -> SetParameterCandidates("none ROOT_default hippodraw");
|
||||
parameter -> SetDefaultValue("ROOT_default");
|
||||
fpCommand -> SetParameter (parameter);
|
||||
#endif
|
||||
}
|
||||
|
||||
G4VisCommandPlot::~G4VisCommandPlot ()
|
||||
@@ -437,9 +443,13 @@ void G4VisCommandPlot::SetNewValue (G4UIcommand*, G4String newValue)
|
||||
return;
|
||||
}
|
||||
|
||||
G4String type, id;
|
||||
std::istringstream is (newValue);
|
||||
G4String type, id;
|
||||
is >> type >> id;
|
||||
#ifdef TOOLS_USE_FREETYPE
|
||||
G4String style;
|
||||
is >> style;
|
||||
#endif
|
||||
|
||||
auto keepEnable = fpVisManager->IsEnabled();
|
||||
|
||||
@@ -455,6 +465,11 @@ void G4VisCommandPlot::SetNewValue (G4UIcommand*, G4String newValue)
|
||||
ui->ApplyCommand("/vis/plotter/create " + plotterName);
|
||||
ui->ApplyCommand("/vis/scene/add/plotter " + plotterName);
|
||||
ui->ApplyCommand("/vis/plotter/add/" + type + ' ' + id + ' ' + plotterName);
|
||||
#ifdef TOOLS_USE_FREETYPE
|
||||
if (style != "none") {
|
||||
ui->ApplyCommand("/vis/plotter/addStyle " + plotterName + ' ' + style);
|
||||
}
|
||||
#endif
|
||||
ui->ApplyCommand("/vis/sceneHandler/attach");
|
||||
|
||||
if (!keepEnable) {
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#define G4warn G4cout
|
||||
|
||||
void G4VVisCommandGeometrySet::Set
|
||||
(G4String requestedName,
|
||||
(const G4String& requestedName,
|
||||
const G4VVisCommandGeometrySetFunction& setFunction,
|
||||
G4int requestedDepth)
|
||||
{
|
||||
|
||||
@@ -27,15 +27,16 @@
|
||||
|
||||
// /vis/multithreading commands - John Allison 29th September 2015
|
||||
|
||||
#include "G4Types.hh"
|
||||
#ifdef G4MULTITHREADED
|
||||
|
||||
#include "G4VisCommandsMultithreading.hh"
|
||||
|
||||
#include "G4Threading.hh"
|
||||
#include "G4UIcmdWithAnInteger.hh"
|
||||
#include "G4UIcmdWithAString.hh"
|
||||
#include "G4VisManager.hh"
|
||||
|
||||
// For future use with additional G4ios logging streams
|
||||
#define G4warn G4cout
|
||||
|
||||
////////////// /vis/multithreading/actionOnEventQueueFull ///////////////////////////////////////
|
||||
|
||||
G4VisCommandMultithreadingActionOnEventQueueFull::G4VisCommandMultithreadingActionOnEventQueueFull()
|
||||
@@ -64,6 +65,14 @@ void G4VisCommandMultithreadingActionOnEventQueueFull::SetNewValue(G4UIcommand*,
|
||||
{
|
||||
G4VisManager::Verbosity verbosity = fpVisManager->GetVerbosity();
|
||||
|
||||
// Only relevant in a MT application
|
||||
if(!G4Threading::IsMultithreadedApplication()) {
|
||||
if (verbosity >= G4VisManager::warnings) {
|
||||
G4warn << "command /vis/multithreading/actionOnEventQueueFull ignored in sequential mode" << G4endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (newValue == "wait") {
|
||||
fpVisManager->SetWaitOnEventQueueFull(true);
|
||||
} else {
|
||||
@@ -116,6 +125,14 @@ void G4VisCommandMultithreadingMaxEventQueueSize::SetNewValue(G4UIcommand*, G4St
|
||||
{
|
||||
G4VisManager::Verbosity verbosity = fpVisManager->GetVerbosity();
|
||||
|
||||
// Only relevant in a MT application
|
||||
if(!G4Threading::IsMultithreadedApplication()) {
|
||||
if (verbosity >= G4VisManager::warnings) {
|
||||
G4warn << "command /vis/multithreading/maxEventQueueSize ignored in sequential mode" << G4endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
G4int maxEventQueueSize = fpCommand->GetNewIntValue(newValue);
|
||||
fpVisManager->SetMaxEventQueueSize(maxEventQueueSize);
|
||||
|
||||
@@ -126,5 +143,3 @@ void G4VisCommandMultithreadingMaxEventQueueSize::SetNewValue(G4UIcommand*, G4St
|
||||
<< G4endl;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -448,7 +448,7 @@ void G4VisCommandSceneAddDate::SetNewValue (G4UIcommand*, G4String newValue)
|
||||
model->SetGlobalTag("Date");
|
||||
model->SetGlobalDescription("Date: " + newValue);
|
||||
const G4String& currentSceneName = pScene -> GetName ();
|
||||
G4bool successful = pScene -> AddRunDurationModel (model, warn);
|
||||
G4bool successful = pScene -> AddEndOfEventModel(model, warn);
|
||||
if (successful) {
|
||||
if (verbosity >= G4VisManager::confirmations) {
|
||||
G4cout << "Date has been added to scene \""
|
||||
@@ -745,8 +745,7 @@ void G4VisCommandSceneAddEventID::EventID::operator()
|
||||
// Only use if NOT reviewing kept events
|
||||
if (fpVisManager->GetReviewingKeptEvents()) return;
|
||||
const G4int nEvents = currentRun->GetNumberOfEventToBeProcessed();
|
||||
const auto* events = currentRun->GetEventVector();
|
||||
size_t nKeptEvents = events? events->size(): 0;
|
||||
size_t nKeptEvents = (size_t)(currentRun->GetNumberOfKeptEvents());
|
||||
oss << "Run " << currentRunID << " (" << nEvents << " event";
|
||||
if (nEvents != 1) oss << 's';
|
||||
oss << ", " << nKeptEvents << " kept)";
|
||||
@@ -1883,7 +1882,11 @@ G4VisCommandSceneAddLogo::G4Logo::G4Logo
|
||||
G4Tubs tG("tG",ri,ro,d2,0.15*pi,1.85*pi);
|
||||
G4Box bG("bG",w2,ro2,d2);
|
||||
G4UnionSolid logoG("logoG",&tG,&bG,G4Translate3D(ri+w2,-ro2,0.));
|
||||
// Create with these vis atts (force solid) and current no of sides per circle.
|
||||
G4Polyhedron::SetNumberOfRotationSteps
|
||||
(fpVisManager->GetCurrentViewer()->GetViewParameters().GetNoOfSides());
|
||||
fpG = logoG.CreatePolyhedron();
|
||||
G4Polyhedron::ResetNumberOfRotationSteps ();
|
||||
fpG->SetVisAttributes(visAtts);
|
||||
fpG->Transform(G4Translate3D(-0.55*h,0.,0.));
|
||||
fpG->Transform(transform);
|
||||
|
||||
@@ -38,7 +38,9 @@
|
||||
#include "G4TouchablePropertiesScene.hh"
|
||||
#include "G4TransportationManager.hh"
|
||||
#include "G4BoundingExtentScene.hh"
|
||||
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
#define G4warn G4cout
|
||||
|
||||
@@ -440,7 +442,7 @@ void G4VisCommandSetTouchable::SetNewValue (G4UIcommand*, G4String newValue)
|
||||
if (iEnd == G4String::npos) {
|
||||
iEnd = newValue.length();
|
||||
}
|
||||
G4String name(newValue.substr(iBegin,iEnd-iBegin));
|
||||
const G4String& name(newValue.substr(iBegin,iEnd-iBegin));
|
||||
iBegin = newValue.find_first_not_of(' ',iEnd);
|
||||
if (iBegin == G4String::npos) {
|
||||
if (verbosity >= G4VisManager::warnings) {
|
||||
|
||||
@@ -1073,16 +1073,6 @@ void G4VisCommandViewerCreate::SetNewValue (G4UIcommand* command, G4String newVa
|
||||
}
|
||||
}
|
||||
|
||||
if (fThereWasAViewer) {
|
||||
// ...and if it's still current...
|
||||
auto existingViewer = fpVisManager->GetCurrentViewer();
|
||||
if (existingViewer) {
|
||||
// ...bring view parameters up to date...
|
||||
fExistingVP = existingViewer->GetViewParameters();
|
||||
fExistingSceneTree = existingViewer->GetSceneTree();
|
||||
}
|
||||
}
|
||||
|
||||
if (fThereWasAViewer && windowSizeHintString == "none") {
|
||||
// The user did not specify a window size hint - get from existing VPs
|
||||
windowSizeHintString = fExistingVP.GetXGeometryString();
|
||||
@@ -1099,6 +1089,7 @@ void G4VisCommandViewerCreate::SetNewValue (G4UIcommand* command, G4String newVa
|
||||
// Copy view parameters from existing viewer, except for...
|
||||
fExistingVP.SetAutoRefresh(vp.IsAutoRefresh());
|
||||
fExistingVP.SetBackgroundColour(vp.GetBackgroundColour());
|
||||
fExistingVP.SetGlobalMarkerScale(vp.GetGlobalMarkerScale());
|
||||
// ...including window hint paramaters that have been set already above...
|
||||
fExistingVP.SetXGeometryString(vp.GetXGeometryString());
|
||||
vp = fExistingVP;
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <utility>
|
||||
|
||||
#define G4warn G4cout
|
||||
|
||||
@@ -1302,7 +1303,7 @@ void G4VisCommandsViewerSet::SetNewValue
|
||||
if (iEnd == G4String::npos) {
|
||||
iEnd = newValue.length();
|
||||
}
|
||||
G4String name(newValue.substr(iBegin,iEnd-iBegin));
|
||||
const G4String& name(newValue.substr(iBegin,iEnd-iBegin));
|
||||
iBegin = newValue.find_first_not_of(' ',iEnd);
|
||||
if (iBegin == G4String::npos) {
|
||||
if (verbosity >= G4VisManager::warnings) {
|
||||
|
||||
@@ -80,19 +80,34 @@
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
# include "G4Threading.hh"
|
||||
# include "G4AutoLock.hh"
|
||||
# include "G4GeometryWorkspace.hh" // no_geant4_module_check(!G4MULTITHREADED)
|
||||
# include "G4SolidsWorkspace.hh"
|
||||
# include <deque>
|
||||
# include <typeinfo>
|
||||
# include <chrono>
|
||||
# include <thread>
|
||||
#endif
|
||||
#include "G4Threading.hh"
|
||||
#include "G4AutoLock.hh"
|
||||
#include "G4GeometryWorkspace.hh" // no_geant4_module_check(!G4MULTITHREADED)
|
||||
#include "G4SolidsWorkspace.hh"
|
||||
#include <deque>
|
||||
#include <typeinfo>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
#define G4warn G4cout
|
||||
|
||||
// Local threading related variables
|
||||
namespace {
|
||||
G4bool mtRunInProgress = false;
|
||||
std::deque<const G4Event*> mtVisEventQueue;
|
||||
G4Thread* mtVisSubThread = 0;
|
||||
[[maybe_unused]] G4Mutex mtVisSubThreadMutex = G4MUTEX_INITIALIZER;
|
||||
// G4Mutex visBeginOfRunMutex = G4MUTEX_INITIALIZER;
|
||||
// G4Mutex visBeginOfEventMutex = G4MUTEX_INITIALIZER;
|
||||
G4Mutex visEndOfEventMutex = G4MUTEX_INITIALIZER;
|
||||
// G4Mutex visEndOfRunMutex = G4MUTEX_INITIALIZER;
|
||||
G4bool isSubEventRunManagerType = false;
|
||||
G4bool isValidViewForRun = false;
|
||||
G4bool isFakeRun = false;
|
||||
}
|
||||
|
||||
// Class statics
|
||||
G4VisManager* G4VisManager::fpInstance = 0;
|
||||
|
||||
G4VisManager::Verbosity G4VisManager::fVerbosity = G4VisManager::warnings;
|
||||
@@ -125,10 +140,8 @@ G4VisManager::G4VisManager (const G4String& verbosityString)
|
||||
, fIsDrawGroup (false)
|
||||
, fDrawGroupNestingDepth (0)
|
||||
, fIgnoreStateChanges (false)
|
||||
#ifdef G4MULTITHREADED
|
||||
, fMaxEventQueueSize (100)
|
||||
, fWaitOnEventQueueFull (true)
|
||||
#endif
|
||||
// All other objects use default constructors.
|
||||
{
|
||||
fpTrajDrawModelMgr = new G4VisModelManager<G4VTrajectoryModel>("/vis/modeling/trajectories");
|
||||
@@ -494,13 +507,11 @@ void G4VisManager::RegisterMessengers () {
|
||||
RegisterMessenger(new G4VisCommandGeometrySetForceWireframe);
|
||||
RegisterMessenger(new G4VisCommandGeometrySetVisibility);
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
directory = new G4UIdirectory ("/vis/multithreading/");
|
||||
directory -> SetGuidance("Commands unique to multithreading mode.");
|
||||
fDirectoryList.push_back (directory);
|
||||
RegisterMessenger(new G4VisCommandMultithreadingActionOnEventQueueFull);
|
||||
RegisterMessenger(new G4VisCommandMultithreadingMaxEventQueueSize);
|
||||
#endif
|
||||
|
||||
directory = new G4UIdirectory ("/vis/set/");
|
||||
directory -> SetGuidance
|
||||
@@ -745,7 +756,7 @@ void G4VisManager::Enable() {
|
||||
if (fVerbosity >= warnings) {
|
||||
std::size_t nKeptEvents = 0;
|
||||
const G4Run* run = G4RunManager::GetRunManager()->GetCurrentRun();
|
||||
if (run) nKeptEvents = run->GetEventVector()->size();
|
||||
if (run) nKeptEvents = run->GetNumberOfKeptEvents();
|
||||
G4String isare("are"),plural("s");
|
||||
if (nKeptEvents == 1) {isare = "is"; plural = "";}
|
||||
G4cout <<
|
||||
@@ -913,9 +924,8 @@ void G4VisManager::SelectTrajectoryModel(const G4String& model)
|
||||
|
||||
void G4VisManager::BeginDraw (const G4Transform3D& objectTransform)
|
||||
{
|
||||
#ifdef G4MULTITHREADED
|
||||
if (G4Threading::IsWorkerThread()) return;
|
||||
#endif
|
||||
|
||||
fDrawGroupNestingDepth++;
|
||||
if (fDrawGroupNestingDepth > 1) {
|
||||
G4Exception
|
||||
@@ -934,9 +944,8 @@ void G4VisManager::BeginDraw (const G4Transform3D& objectTransform)
|
||||
|
||||
void G4VisManager::EndDraw ()
|
||||
{
|
||||
#ifdef G4MULTITHREADED
|
||||
if (G4Threading::IsWorkerThread()) return;
|
||||
#endif
|
||||
|
||||
fDrawGroupNestingDepth--;
|
||||
if (fDrawGroupNestingDepth != 0) {
|
||||
if (fDrawGroupNestingDepth < 0) fDrawGroupNestingDepth = 0;
|
||||
@@ -950,9 +959,8 @@ void G4VisManager::EndDraw ()
|
||||
|
||||
void G4VisManager::BeginDraw2D (const G4Transform3D& objectTransform)
|
||||
{
|
||||
#ifdef G4MULTITHREADED
|
||||
if (G4Threading::IsWorkerThread()) return;
|
||||
#endif
|
||||
|
||||
fDrawGroupNestingDepth++;
|
||||
if (fDrawGroupNestingDepth > 1) {
|
||||
G4Exception
|
||||
@@ -971,9 +979,8 @@ void G4VisManager::BeginDraw2D (const G4Transform3D& objectTransform)
|
||||
|
||||
void G4VisManager::EndDraw2D ()
|
||||
{
|
||||
#ifdef G4MULTITHREADED
|
||||
if (G4Threading::IsWorkerThread()) return;
|
||||
#endif
|
||||
|
||||
fDrawGroupNestingDepth--;
|
||||
if (fDrawGroupNestingDepth != 0) {
|
||||
if (fDrawGroupNestingDepth < 0) fDrawGroupNestingDepth = 0;
|
||||
@@ -987,9 +994,8 @@ void G4VisManager::EndDraw2D ()
|
||||
|
||||
template <class T> void G4VisManager::DrawT
|
||||
(const T& graphics_primitive, const G4Transform3D& objectTransform) {
|
||||
#ifdef G4MULTITHREADED
|
||||
if (G4Threading::IsWorkerThread()) return;
|
||||
#endif
|
||||
|
||||
if (fIsDrawGroup) {
|
||||
if (objectTransform != fpSceneHandler->GetObjectTransformation()) {
|
||||
G4Exception
|
||||
@@ -1010,9 +1016,8 @@ template <class T> void G4VisManager::DrawT
|
||||
|
||||
template <class T> void G4VisManager::DrawT2D
|
||||
(const T& graphics_primitive, const G4Transform3D& objectTransform) {
|
||||
#ifdef G4MULTITHREADED
|
||||
if (G4Threading::IsWorkerThread()) return;
|
||||
#endif
|
||||
|
||||
if (fIsDrawGroup) {
|
||||
if (objectTransform != fpSceneHandler->GetObjectTransformation()) {
|
||||
G4Exception
|
||||
@@ -1104,9 +1109,8 @@ void G4VisManager::Draw2D (const G4Text& text,
|
||||
}
|
||||
|
||||
void G4VisManager::Draw (const G4VHit& hit) {
|
||||
#ifdef G4MULTITHREADED
|
||||
if (G4Threading::IsWorkerThread()) return;
|
||||
#endif
|
||||
|
||||
if (fIsDrawGroup) {
|
||||
fpSceneHandler -> AddCompound (hit);
|
||||
} else {
|
||||
@@ -1118,9 +1122,8 @@ void G4VisManager::Draw (const G4VHit& hit) {
|
||||
}
|
||||
|
||||
void G4VisManager::Draw (const G4VDigi& digi) {
|
||||
#ifdef G4MULTITHREADED
|
||||
if (G4Threading::IsWorkerThread()) return;
|
||||
#endif
|
||||
|
||||
if (fIsDrawGroup) {
|
||||
fpSceneHandler -> AddCompound (digi);
|
||||
} else {
|
||||
@@ -1132,9 +1135,8 @@ void G4VisManager::Draw (const G4VDigi& digi) {
|
||||
}
|
||||
|
||||
void G4VisManager::Draw (const G4VTrajectory& traj) {
|
||||
#ifdef G4MULTITHREADED
|
||||
if (G4Threading::IsWorkerThread()) return;
|
||||
#endif
|
||||
|
||||
// A trajectory needs a trajectories model to provide G4Atts, etc.
|
||||
static G4TrajectoriesModel trajectoriesModel;
|
||||
trajectoriesModel.SetCurrentTrajectory(&traj);
|
||||
@@ -1165,9 +1167,8 @@ void G4VisManager::Draw (const G4VTrajectory& traj) {
|
||||
void G4VisManager::Draw (const G4LogicalVolume& logicalVol,
|
||||
const G4VisAttributes& attribs,
|
||||
const G4Transform3D& objectTransform) {
|
||||
#ifdef G4MULTITHREADED
|
||||
if (G4Threading::IsWorkerThread()) return;
|
||||
#endif
|
||||
|
||||
// Find corresponding solid.
|
||||
G4VSolid* pSol = logicalVol.GetSolid ();
|
||||
Draw (*pSol, attribs, objectTransform);
|
||||
@@ -1176,9 +1177,8 @@ void G4VisManager::Draw (const G4LogicalVolume& logicalVol,
|
||||
void G4VisManager::Draw (const G4VSolid& solid,
|
||||
const G4VisAttributes& attribs,
|
||||
const G4Transform3D& objectTransform) {
|
||||
#ifdef G4MULTITHREADED
|
||||
if (G4Threading::IsWorkerThread()) return;
|
||||
#endif
|
||||
|
||||
if (fIsDrawGroup) {
|
||||
fpSceneHandler -> PreAddSolid (objectTransform, attribs);
|
||||
solid.DescribeYourselfTo (*fpSceneHandler);
|
||||
@@ -1196,9 +1196,8 @@ void G4VisManager::Draw (const G4VSolid& solid,
|
||||
void G4VisManager::Draw (const G4VPhysicalVolume& physicalVol,
|
||||
const G4VisAttributes& attribs,
|
||||
const G4Transform3D& objectTransform) {
|
||||
#ifdef G4MULTITHREADED
|
||||
if (G4Threading::IsWorkerThread()) return;
|
||||
#endif
|
||||
|
||||
// Note: It is tempting to use a temporary model here, as for
|
||||
// trajectories, in order to get at the G4Atts of the physical
|
||||
// volume. I tried it (JA). But it's not easy to pass the
|
||||
@@ -1867,13 +1866,15 @@ void G4VisManager::PrintAvailableUserVisActions (Verbosity) const
|
||||
|
||||
void G4VisManager::PrintAvailableColours (Verbosity) const {
|
||||
G4cout <<
|
||||
"Some /vis commands (optionally) take a string to specify colour."
|
||||
"\nAvailable colours:\n ";
|
||||
const std::map<G4String, G4Colour>& map = G4Colour::GetMap();
|
||||
for (std::map<G4String, G4Colour>::const_iterator i = map.begin();
|
||||
i != map.end();) {
|
||||
G4cout << i->first;
|
||||
if (++i != map.end()) G4cout << ", ";
|
||||
"Some /vis commands (optionally) take a string to specify colour."
|
||||
"\nThey are also available in your C++ code, e.g:"
|
||||
"\n G4Colour niceColour; // Default - white"
|
||||
"\n G4Colour::GetColour(\"pink\", niceColour);"
|
||||
"\n logical->SetVisAttributes(niceColour);"
|
||||
"\nSee G4Colour.hh."
|
||||
"\nAvailable colours";
|
||||
for (const auto& i: G4Colour::GetMap()) {
|
||||
G4cout << ", " << i.first;
|
||||
}
|
||||
G4cout << G4endl;
|
||||
}
|
||||
@@ -1903,17 +1904,10 @@ void G4VisManager::PrintInvalidPointers () const {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
|
||||
namespace {
|
||||
G4bool mtRunInProgress = false;
|
||||
std::deque<const G4Event*> mtVisEventQueue;
|
||||
G4Thread* mtVisSubThread = 0;
|
||||
G4Mutex mtVisSubThreadMutex = G4MUTEX_INITIALIZER;
|
||||
}
|
||||
|
||||
G4ThreadFunReturnType G4VisManager::G4VisSubThread(G4ThreadFunArgType p)
|
||||
{
|
||||
#ifdef G4MULTITHREADED
|
||||
G4VisManager* pVisManager = (G4VisManager*)p;
|
||||
G4VSceneHandler* pSceneHandler = pVisManager->GetCurrentSceneHandler();
|
||||
if (!pSceneHandler) return 0;
|
||||
@@ -1924,9 +1918,6 @@ G4ThreadFunReturnType G4VisManager::G4VisSubThread(G4ThreadFunArgType p)
|
||||
|
||||
G4UImanager::GetUIpointer()->SetUpForSpecialThread("G4VIS");
|
||||
|
||||
// G4cout << "G4VisManager::G4VisSubThread: thread: "
|
||||
// << G4Threading::G4GetThreadId() << std::endl;
|
||||
|
||||
// Set up geometry and navigation for a thread
|
||||
G4GeometryWorkspace::GetPool()->CreateAndUseWorkspace();
|
||||
G4SolidsWorkspace::GetPool()->CreateAndUseWorkspace();
|
||||
@@ -1949,11 +1940,6 @@ G4ThreadFunReturnType G4VisManager::G4VisSubThread(G4ThreadFunArgType p)
|
||||
G4MUTEXLOCK(&mtVisSubThreadMutex);
|
||||
const G4Event* event = mtVisEventQueue.front();
|
||||
G4MUTEXUNLOCK(&mtVisSubThreadMutex);
|
||||
// G4int eventID = event->GetEventID();
|
||||
// G4cout
|
||||
// << "G4VisManager::G4VisSubThread: Vis sub-thread: Dealing with event:
|
||||
// "
|
||||
// << eventID << G4endl;
|
||||
|
||||
// Here comes the event drawing
|
||||
pVisManager->SetTransientsDrawnThisEvent(false);
|
||||
@@ -1973,26 +1959,12 @@ G4ThreadFunReturnType G4VisManager::G4VisSubThread(G4ThreadFunArgType p)
|
||||
pSceneHandler->DrawEvent(event);
|
||||
++pVisManager->fNoOfEventsDrawnThisRun;
|
||||
|
||||
if (pScene->GetRefreshAtEndOfEvent()) {
|
||||
|
||||
// ShowView guarantees the view is flushed to the screen. It also
|
||||
// triggers other features such picking (if enabled) and allows
|
||||
// file-writing viewers to close the file.
|
||||
pViewer->ShowView();
|
||||
pSceneHandler->SetMarkForClearingTransientStore(true);
|
||||
|
||||
}
|
||||
|
||||
// Testing.
|
||||
// std::this_thread::sleep_for(std::chrono::seconds(5));
|
||||
|
||||
// Then pop and release event
|
||||
G4MUTEXLOCK(&mtVisSubThreadMutex);
|
||||
mtVisEventQueue.pop_front();
|
||||
pVisManager->EndOfEventCleanup(event, event->GetEventID());
|
||||
pVisManager->EndOfEventCleanup(event);
|
||||
eventQueueSize = mtVisEventQueue.size();
|
||||
G4MUTEXUNLOCK(&mtVisSubThreadMutex);
|
||||
// G4cout << "Event queue size (B): " << eventQueueSize << G4endl;
|
||||
}
|
||||
|
||||
G4MUTEXLOCK(&mtVisSubThreadMutex);
|
||||
@@ -2011,46 +1983,35 @@ G4ThreadFunReturnType G4VisManager::G4VisSubThread(G4ThreadFunArgType p)
|
||||
// Inform viewer that we have finished all sub-thread drawing
|
||||
pViewer->DoneWithVisSubThread();
|
||||
pViewer->MovingToMasterThread();
|
||||
// G4cout << "G4VisManager::G4VisSubThread: Vis sub-thread: ending" << G4endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
namespace {
|
||||
// G4Mutex visBeginOfRunMutex = G4MUTEX_INITIALIZER;
|
||||
// G4Mutex visBeginOfEventMutex = G4MUTEX_INITIALIZER;
|
||||
G4Mutex visEndOfEventMutex = G4MUTEX_INITIALIZER;
|
||||
// G4Mutex visEndOfRunMutex = G4MUTEX_INITIALIZER;
|
||||
}
|
||||
|
||||
#else
|
||||
G4ConsumeParameters(p);
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
G4bool isSubEventRunManagerType = false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void G4VisManager::BeginOfRun ()
|
||||
{
|
||||
if (fIgnoreStateChanges) return;
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
if (G4Threading::IsWorkerThread()) return;
|
||||
#endif
|
||||
// G4cout << "G4VisManager::BeginOfRun: thread: "
|
||||
// << G4Threading::G4GetThreadId() << G4endl;
|
||||
if (!GetConcreteInstance()) return;
|
||||
|
||||
// Check if view is valid
|
||||
// Protect IsValidView() with fpSceneHandler to prevent warning messages in batch
|
||||
isValidViewForRun = fpSceneHandler && IsValidView();
|
||||
if (!isValidViewForRun) return;
|
||||
|
||||
// For a fake run...
|
||||
G4RunManager* runManager = G4RunManagerFactory::GetMasterRunManager();
|
||||
G4int nEventsToBeProcessed = runManager->GetNumberOfEventsToBeProcessed();
|
||||
isFakeRun = (nEventsToBeProcessed == 0);
|
||||
if (isFakeRun) return;
|
||||
|
||||
// Is the run manager a sub-event type?
|
||||
G4RunManager::RMType rmType = runManager->GetRunManagerType();
|
||||
isSubEventRunManagerType =
|
||||
(rmType == G4RunManager::subEventMasterRM) ||
|
||||
(rmType == G4RunManager::subEventWorkerRM);
|
||||
|
||||
// If sub-event active, ignore if invoked from worker thread
|
||||
if(isSubEventRunManagerType && G4Threading::IsWorkerThread()) return;
|
||||
|
||||
// For a fake run...
|
||||
G4int nEventsToBeProcessed = runManager->GetNumberOfEventsToBeProcessed();
|
||||
if (nEventsToBeProcessed == 0) return;
|
||||
|
||||
fNKeepForPostProcessingRequests = 0;
|
||||
fNKeepTheEventRequests = 0;
|
||||
fEventKeepingSuspended = false;
|
||||
@@ -2064,19 +2025,13 @@ void G4VisManager::BeginOfRun ()
|
||||
// The function is called again later when needed.
|
||||
CurrentTrajDrawModel();
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
// There is a static method G4Threading::IsMultithreadedApplication()
|
||||
// that returns true only if G4MTRunManager is instantiated with MT
|
||||
// installation. Thus method returns false if G4RunManager base class is
|
||||
// instantiated even with the MT installation, or of course with sequential
|
||||
// installation.
|
||||
// Actions only in MT mode
|
||||
if (G4Threading::IsMultithreadedApplication()) {
|
||||
|
||||
// Inform viewer that we have finished all master thread drawing for now...
|
||||
if (fpViewer) fpViewer->DoneWithMasterThread();
|
||||
|
||||
// Start vis sub-thread
|
||||
// G4cout << "G4VisManager::BeginOfRun: Starting vis sub-thread" << G4endl;
|
||||
G4MUTEXLOCK(&mtVisSubThreadMutex);
|
||||
mtRunInProgress = true;
|
||||
G4MUTEXUNLOCK(&mtVisSubThreadMutex);
|
||||
@@ -2091,21 +2046,17 @@ void G4VisManager::BeginOfRun ()
|
||||
// - Go ahead
|
||||
if (fpViewer) fpViewer->MovingToVisSubThread();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void G4VisManager::BeginOfEvent ()
|
||||
{
|
||||
if (fIgnoreStateChanges) return;
|
||||
|
||||
if (!GetConcreteInstance()) return;
|
||||
|
||||
if (isSubEventRunManagerType) return;
|
||||
|
||||
// G4cout << "G4VisManager::BeginOfEvent: thread: "
|
||||
// << G4Threading::G4GetThreadId() << G4endl;
|
||||
if (!isValidViewForRun) return;
|
||||
if (isFakeRun) return;
|
||||
|
||||
// Some instructions that should NOT be in multithreaded version.
|
||||
// TODO: protect with G4Threading::IsMultithreadedApplication() instead?
|
||||
#ifndef G4MULTITHREADED
|
||||
// These instructions are in G4VisSubThread for multithreading.
|
||||
fTransientsDrawnThisEvent = false;
|
||||
@@ -2113,52 +2064,51 @@ void G4VisManager::BeginOfEvent ()
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
void G4VisManager::EventReadyForVis(const G4Event* event)
|
||||
// This is invoked by G4SubEvtRunManager.
|
||||
// The event is passed to EndOfEventKernel.
|
||||
{
|
||||
if (fIgnoreStateChanges) return;
|
||||
|
||||
if (!GetConcreteInstance()) return;
|
||||
|
||||
G4bool valid = fpSceneHandler && IsValidView();
|
||||
if (!valid) return;
|
||||
|
||||
G4AutoLock al(&visEndOfEventMutex);
|
||||
EndOfEventKernel(event);
|
||||
}
|
||||
#endif
|
||||
// Here begins a sequence of functions that deal with end-of-event.
|
||||
// Sequential/Serial mode:
|
||||
// EndOfEvent is invoked by a state change on the master thread:
|
||||
// EndOfEvent pulls the event from the Event Manager and calls EndOfEventKernel.
|
||||
// EndOfEventKernel draws the event and calls EndOfEventCleanup.
|
||||
// (Unless the user him/herself has requested keeping, EndOfEventKernel
|
||||
// also sets KeepTheEvent for a certain number (adjustable, default 100)
|
||||
// of events. The run manager keeps these events until the beginning of the next
|
||||
// run, so, for example, the vis manager can redraw/rebuild if required.)
|
||||
// Multithreading/Tasking:
|
||||
// EndOfEvent is invoked by a state change on each worker thread:
|
||||
// EndOfEvent pulls the event from the (worker) Event Manager and calls EndOfEventKernel.
|
||||
// EndOfEventKernel pushes it to the vis queue, and returns. The events
|
||||
// are marked KeepForPostProcessing so that the worker does not delete them until
|
||||
// PostProcessingFinished in EndOfEventCleanup.
|
||||
// EndOfEventKernel also sets KeepTheEvent as above.
|
||||
// The vis sub thread pulls events from the vis queue, draws them and
|
||||
// calls EndOfEventCleanup, which calls PostProcessingFinished.
|
||||
// Sub-event parallelism:
|
||||
// EndOfEvent is invoked by a state change on each worker thread, as for
|
||||
// multithreading, but actually, the event is not complete. Workers are
|
||||
// employed on sub-events, so we ignore such state changes. Only
|
||||
// G4SubEvtRunManager knows when the event is complete.
|
||||
// Events are pushed to the Vis Manager by G4SubEvtRunManager via EventReadyForVis
|
||||
// when the event is ready. EventReadyForVis calls EndOfEventKernel and
|
||||
// processsing continues as for Multithreading.
|
||||
|
||||
void G4VisManager::EndOfEvent ()
|
||||
{
|
||||
if (fIgnoreStateChanges) return;
|
||||
|
||||
if (!GetConcreteInstance()) return;
|
||||
if (!isValidViewForRun) return;
|
||||
if (isFakeRun) return;
|
||||
|
||||
// For sub-event parallelism, this is not the true end of event
|
||||
if (isSubEventRunManagerType) return;
|
||||
|
||||
// G4cout << "G4VisManager::EndOfEvent: thread: "
|
||||
// << G4Threading::G4GetThreadId() << G4endl;
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
G4AutoLock al(&visEndOfEventMutex);
|
||||
// Testing.
|
||||
// std::this_thread::sleep_for(std::chrono::seconds(5));
|
||||
#endif
|
||||
|
||||
// Don't call IsValidView unless there is a scene handler. This
|
||||
// avoids WARNING message at end of event and run when the user has
|
||||
// not instantiated a scene handler, e.g., in batch mode.
|
||||
G4bool valid = fpSceneHandler && IsValidView();
|
||||
if (!valid) return;
|
||||
|
||||
G4RunManager* runManager = G4RunManagerFactory::GetMasterRunManager();
|
||||
|
||||
const G4Run* currentRun = runManager->GetCurrentRun();
|
||||
if (!currentRun) return;
|
||||
|
||||
// This gets the thread-local event manager
|
||||
// This gets the appropriate event manager
|
||||
G4EventManager* eventManager = G4EventManager::GetEventManager();
|
||||
const G4Event* currentEvent = eventManager->GetConstCurrentEvent();
|
||||
if (!currentEvent) return;
|
||||
@@ -2167,72 +2117,22 @@ void G4VisManager::EndOfEvent ()
|
||||
EndOfEventKernel(currentEvent);
|
||||
}
|
||||
|
||||
G4bool G4VisManager::Relinquishable (G4int eventID, G4int nKeptEvents, G4int nRequests)
|
||||
// Figures out if event is relinquishable, i.e., the run manager(s) may delete.
|
||||
// If _not_ relinquishable, KeepCurrentEvent is called as soon as event is recieved.
|
||||
// If relinquishable, PostProcesssingFinshed is called when drawing finished.
|
||||
// nKeptEvents is number of events currently kept by the run manager.
|
||||
// nRequests is the number of requests for keeping made by the vis maanager.
|
||||
void G4VisManager::EventReadyForVis(const G4Event* event)
|
||||
// This is invoked by G4SubEvtRunManager.
|
||||
// The event is passed to EndOfEventKernel.
|
||||
{
|
||||
G4bool relinquishable = false;
|
||||
if (fIgnoreStateChanges) return;
|
||||
if (!GetConcreteInstance()) return;
|
||||
if (!isValidViewForRun) return;
|
||||
if (isFakeRun) return;
|
||||
|
||||
G4RunManager* runManager = G4RunManagerFactory::GetMasterRunManager();
|
||||
G4int nEventsToBeProcessed = runManager->GetNumberOfEventsToBeProcessed();
|
||||
|
||||
if (fpScene->GetRefreshAtEndOfEvent()) {
|
||||
|
||||
// Unless last event (in which case wait end of run)...
|
||||
if (eventID < nEventsToBeProcessed - 1) {
|
||||
relinquishable = true;
|
||||
} else { // Last event - relinquish too if user has kept some
|
||||
if (nKeptEvents > 0) {
|
||||
relinquishable = true;
|
||||
}
|
||||
}
|
||||
fpSceneHandler->SetMarkForClearingTransientStore(true);
|
||||
|
||||
} else { // Accumulating events...
|
||||
|
||||
G4int maxNumberOfKeptEvents = fpScene->GetMaxNumberOfKeptEvents();
|
||||
|
||||
if (maxNumberOfKeptEvents >= 0 &&
|
||||
nRequests >= maxNumberOfKeptEvents) {
|
||||
|
||||
fEventKeepingSuspended = true;
|
||||
static G4bool warned = false;
|
||||
if (!warned) {
|
||||
if (fVerbosity >= warnings) {
|
||||
G4warn <<
|
||||
"WARNING: G4VisManager::EndOfEvent: Automatic event keeping suspended."
|
||||
<< G4endl;
|
||||
if (maxNumberOfKeptEvents > 0) {
|
||||
G4warn <<
|
||||
"\n The number of events exceeds the maximum, "
|
||||
<< maxNumberOfKeptEvents <<
|
||||
", that may be kept by\n the vis manager."
|
||||
<< G4endl;
|
||||
}
|
||||
}
|
||||
warned = true;
|
||||
}
|
||||
relinquishable = true;
|
||||
|
||||
} else if (maxNumberOfKeptEvents != 0) { // i.e., indefinite keeping
|
||||
|
||||
// Relinquish anyway if disabled or suspended
|
||||
if (!GetConcreteInstance() || fEventKeepingSuspended) {
|
||||
relinquishable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return relinquishable;
|
||||
G4AutoLock al(&visEndOfEventMutex);
|
||||
EndOfEventKernel(event);
|
||||
}
|
||||
|
||||
void G4VisManager::EndOfEventKernel (const G4Event* currentEvent)
|
||||
{
|
||||
G4RunManager* runManager = G4RunManagerFactory::GetMasterRunManager();
|
||||
const G4Run* currentRun = runManager->GetCurrentRun();
|
||||
G4EventManager* eventManager = G4EventManager::GetEventManager();
|
||||
// Note: we are still subject to the mutex lock with visEndOfEventMutex
|
||||
|
||||
// Discard event if fDrawEventOnlyIfToBeKept flag is set unless the
|
||||
// user has requested the event to be kept.
|
||||
@@ -2242,19 +2142,16 @@ void G4VisManager::EndOfEventKernel (const G4Event* currentEvent)
|
||||
|
||||
if (G4Threading::IsMultithreadedApplication()) {
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
|
||||
// Wait if too many events in the queue.
|
||||
G4MUTEXLOCK(&mtVisSubThreadMutex);
|
||||
std::size_t eventQueueSize = mtVisEventQueue.size();
|
||||
G4MUTEXUNLOCK(&mtVisSubThreadMutex);
|
||||
// G4cout << "Event queue size (1): " << eventQueueSize << G4endl;
|
||||
|
||||
G4bool eventQueueFull = false;
|
||||
while (fMaxEventQueueSize > 0 && (G4int)eventQueueSize >= fMaxEventQueueSize) {
|
||||
|
||||
// G4cout << "Event queue size (2): " << eventQueueSize << G4endl;
|
||||
if (fWaitOnEventQueueFull) {
|
||||
|
||||
static G4bool warned = false;
|
||||
if (!warned) {
|
||||
G4warn <<
|
||||
@@ -2274,11 +2171,12 @@ void G4VisManager::EndOfEventKernel (const G4Event* currentEvent)
|
||||
<< G4endl;
|
||||
warned = true;
|
||||
}
|
||||
// G4cout << "Event queue size (3): " << eventQueueSize << G4endl;
|
||||
|
||||
// Wait a while to give event drawing time to reduce the queue...
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
// G4cout << "Event queue size (4): " << eventQueueSize << G4endl;
|
||||
|
||||
} else {
|
||||
|
||||
static G4bool warned = false;
|
||||
if (!warned) {
|
||||
G4warn <<
|
||||
@@ -2292,6 +2190,7 @@ void G4VisManager::EndOfEventKernel (const G4Event* currentEvent)
|
||||
<< G4endl;
|
||||
warned = true;
|
||||
}
|
||||
|
||||
eventQueueFull = true; // Causes event to be discarded for drawing.
|
||||
break;
|
||||
}
|
||||
@@ -2302,37 +2201,29 @@ void G4VisManager::EndOfEventKernel (const G4Event* currentEvent)
|
||||
}
|
||||
|
||||
if (!eventQueueFull) {
|
||||
|
||||
if (RequiredToBeKeptForVis(currentEvent->GetEventID())) {
|
||||
currentEvent->KeepTheEvent();
|
||||
fNKeepTheEventRequests++; // Counts number of calls to KeepTheEvent
|
||||
}
|
||||
|
||||
G4MUTEXLOCK(&mtVisSubThreadMutex);
|
||||
|
||||
// Keep while post processing (i.e., drawing), relinquished in EndOfEventCleanup
|
||||
// Make sure the event is not deleted by the run manager while in the vis queue
|
||||
currentEvent->KeepForPostProcessing();
|
||||
fNKeepForPostProcessingRequests++;
|
||||
if (!Relinquishable(currentEvent->GetEventID(),
|
||||
(G4int)currentRun->GetEventVector()->size(),
|
||||
fNKeepTheEventRequests)) {
|
||||
eventManager->KeepTheCurrentEvent();
|
||||
fNKeepTheEventRequests++; // Counts number of calls to KeepTheCurrentEvent
|
||||
}
|
||||
G4MUTEXLOCK(&mtVisSubThreadMutex);
|
||||
|
||||
// Put event on vis queue
|
||||
mtVisEventQueue.push_back(currentEvent);
|
||||
|
||||
G4MUTEXUNLOCK(&mtVisSubThreadMutex);
|
||||
}
|
||||
|
||||
// G4MUTEXLOCK(&mtVisSubThreadMutex);
|
||||
// G4int eQS = mtVisEventQueue.size();
|
||||
// G4MUTEXUNLOCK(&mtVisSubThreadMutex);
|
||||
// G4cout << "Event queue size (5): " << eQS << G4endl;
|
||||
|
||||
#endif
|
||||
|
||||
} else {
|
||||
|
||||
// Sequential mode
|
||||
|
||||
G4int eventID = -2; // (If no run manager, triggers ShowView as normal.)
|
||||
if (currentRun) {
|
||||
eventID = currentEvent->GetEventID();
|
||||
}
|
||||
|
||||
// We are about to draw the event (trajectories, etc.), but first we
|
||||
// have to clear the previous event(s) if necessary. If this event
|
||||
// needs to be drawn afresh, e.g., the first event or any event when
|
||||
@@ -2343,59 +2234,103 @@ void G4VisManager::EndOfEventKernel (const G4Event* currentEvent)
|
||||
// See, for example, G4HepRepFileSceneHandler::ClearTransientStore.
|
||||
ClearTransientStoreIfMarked();
|
||||
|
||||
// Keep - but relinquish (PostProcessingFinished) later if not needed
|
||||
// Keep while post processing (i.e., drawing), relinquished in EndOfEventCleanup
|
||||
currentEvent->KeepForPostProcessing();
|
||||
if (!Relinquishable(currentEvent->GetEventID(),
|
||||
(G4int)currentRun->GetEventVector()->size(),
|
||||
fNKeepTheEventRequests)) {
|
||||
eventManager->KeepTheCurrentEvent();
|
||||
fNKeepTheEventRequests++; // Counts number of calls to KeepTheCurrentEvent
|
||||
fNKeepForPostProcessingRequests++;
|
||||
|
||||
if (RequiredToBeKeptForVis(currentEvent->GetEventID())) {
|
||||
currentEvent->KeepTheEvent();
|
||||
fNKeepTheEventRequests++; // Counts number of calls to KeepTheEvent
|
||||
}
|
||||
|
||||
// Now draw the event...
|
||||
fpSceneHandler->DrawEvent(currentEvent);
|
||||
++fNoOfEventsDrawnThisRun;
|
||||
|
||||
EndOfEventCleanup(currentEvent,eventID);
|
||||
EndOfEventCleanup(currentEvent);
|
||||
}
|
||||
}
|
||||
|
||||
void G4VisManager::EndOfEventCleanup
|
||||
(const G4Event* currentEvent,
|
||||
G4int eventID) // See EndOfEventKernel: can be == -2?
|
||||
void G4VisManager::EndOfEventCleanup(const G4Event* currentEvent)
|
||||
{
|
||||
G4RunManager* runManager = G4RunManagerFactory::GetMasterRunManager();
|
||||
G4int nKeptEvents = 0;
|
||||
const G4Run* currentRun = runManager->GetCurrentRun();
|
||||
if (currentRun) {
|
||||
const std::vector<const G4Event*>* events = currentRun->GetEventVector();
|
||||
if (events) nKeptEvents = (G4int)events->size();
|
||||
if (fpScene->GetRefreshAtEndOfEvent()) {
|
||||
|
||||
fpSceneHandler->SetMarkForClearingTransientStore(true);
|
||||
|
||||
// ShowView guarantees the view is flushed to the screen. It also
|
||||
// triggers other features such as picking (if enabled) and allows
|
||||
// file-writing viewers to close the file.
|
||||
fpViewer->ShowView();
|
||||
}
|
||||
|
||||
// Seems to relinquish every event - probably becuase it doesn't get here soon enough.
|
||||
// In fact, it makes sense to do this - immediate post processing is finished,
|
||||
// and a user-requested number of events have been kept. So great!
|
||||
if (Relinquishable(eventID, nKeptEvents, fNKeepForPostProcessingRequests)) {
|
||||
currentEvent->PostProcessingFinished();
|
||||
if (fpScene->GetRefreshAtEndOfEvent()) { // && eventID == -2?
|
||||
// ShowView guarantees the view is flushed to the screen. It also
|
||||
// triggers other features such picking (if enabled) and allows
|
||||
// file-writing viewers to close the file.
|
||||
fpViewer->ShowView();
|
||||
currentEvent->PostProcessingFinished();
|
||||
}
|
||||
|
||||
G4bool G4VisManager::RequiredToBeKeptForVis (G4int eventID)
|
||||
// i.e., kept by the run manager at least to the beginning of the next run.
|
||||
{
|
||||
G4bool requiredToBeKept = false;
|
||||
|
||||
G4RunManager* runManager = G4RunManagerFactory::GetMasterRunManager();
|
||||
G4int nEventsToBeProcessed = runManager->GetNumberOfEventsToBeProcessed();
|
||||
|
||||
if (fpScene->GetRefreshAtEndOfEvent()) { // Refreshing every event
|
||||
|
||||
// Keep last event only
|
||||
if (eventID == nEventsToBeProcessed - 1) {
|
||||
requiredToBeKept = true;
|
||||
}
|
||||
|
||||
} else { // Accumulating events
|
||||
|
||||
G4int maxNumberOfKeptEvents = fpScene->GetMaxNumberOfKeptEvents();
|
||||
|
||||
if (maxNumberOfKeptEvents >= 0) { // Event keeping requested
|
||||
|
||||
if (fNKeepTheEventRequests < maxNumberOfKeptEvents) {
|
||||
|
||||
// Not yet reached the limit
|
||||
requiredToBeKept = true;
|
||||
|
||||
} else {
|
||||
|
||||
// We have already reached the limit
|
||||
fEventKeepingSuspended = true;
|
||||
static G4bool warned = false;
|
||||
if (!warned) {
|
||||
if (fVerbosity >= warnings) {
|
||||
G4warn <<
|
||||
"WARNING: G4VisManager::EndOfEvent: Automatic event keeping suspended."
|
||||
<< G4endl;
|
||||
if (maxNumberOfKeptEvents > 0) {
|
||||
G4warn <<
|
||||
"\n The number of events exceeds the maximum, "
|
||||
<< maxNumberOfKeptEvents <<
|
||||
", that may be kept by\n the vis manager."
|
||||
<< G4endl;
|
||||
}
|
||||
}
|
||||
warned = true;
|
||||
}
|
||||
}
|
||||
|
||||
} else { // Indefinite event keeping (maxNumberOfKeptEvents < 0)
|
||||
|
||||
requiredToBeKept = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return requiredToBeKept;
|
||||
}
|
||||
|
||||
void G4VisManager::EndOfRun ()
|
||||
{
|
||||
if (fIgnoreStateChanges) return;
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
if (G4Threading::IsWorkerThread()) return;
|
||||
#endif
|
||||
|
||||
// G4cout << "G4VisManager::EndOfRun: thread: "
|
||||
// << G4Threading::G4GetThreadId() << G4endl;
|
||||
if (!GetConcreteInstance()) return;
|
||||
if (!isValidViewForRun) return;
|
||||
if (isFakeRun) return;
|
||||
|
||||
G4RunManager* runManager = G4RunManagerFactory::GetMasterRunManager();
|
||||
|
||||
@@ -2406,7 +2341,6 @@ void G4VisManager::EndOfRun ()
|
||||
const G4Run* currentRun = runManager->GetCurrentRun();
|
||||
if (!currentRun) return;
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
// G4AutoLock al(&visEndOfRunMutex); ???
|
||||
if (G4Threading::IsMultithreadedApplication()) {
|
||||
// Reset flag so that sub-thread exits when it has finished processing.
|
||||
@@ -2416,16 +2350,10 @@ void G4VisManager::EndOfRun ()
|
||||
// Wait for sub-thread to finish.
|
||||
G4THREADJOIN(*mtVisSubThread);
|
||||
delete mtVisSubThread;
|
||||
if (fpViewer) fpViewer->SwitchToMasterThread();
|
||||
fpViewer->SwitchToMasterThread();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
// Print warning about discarded events, if any.
|
||||
// Don't call IsValidView unless there is a scene handler. This
|
||||
// avoids WARNING message from IsValidView() when the user has
|
||||
// not instantiated a scene handler, e.g., in batch mode.
|
||||
if (fpSceneHandler && IsValidView()) { // Events should have been drawn
|
||||
if (G4Threading::IsMultithreadedApplication()) {
|
||||
G4int noOfEventsRequested = runManager->GetNumberOfEventsToBeProcessed();
|
||||
if (fNoOfEventsDrawnThisRun != noOfEventsRequested) {
|
||||
if (!fWaitOnEventQueueFull && fVerbosity >= warnings) {
|
||||
@@ -2438,18 +2366,14 @@ void G4VisManager::EndOfRun ()
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
G4int nKeptEvents = 0;
|
||||
const std::vector<const G4Event*>* events = currentRun->GetEventVector();
|
||||
if (events) nKeptEvents = (G4int)events->size();
|
||||
G4int nKeptEvents = currentRun->GetNumberOfKeptEvents();
|
||||
if (fVerbosity >= warnings && nKeptEvents > 0) {
|
||||
G4warn << nKeptEvents;
|
||||
if (nKeptEvents == 1) G4warn << " event has";
|
||||
else G4warn << " events have";
|
||||
G4warn << " been kept for refreshing and/or reviewing." << G4endl;
|
||||
if (nKeptEvents != fNKeepTheEventRequests) {
|
||||
G4warn << " (Note: ";
|
||||
if (fNKeepTheEventRequests == 0) {
|
||||
G4warn << "No keep requests were";
|
||||
} else if (fNKeepTheEventRequests == 1) {
|
||||
@@ -2460,10 +2384,12 @@ void G4VisManager::EndOfRun ()
|
||||
G4warn << " made by the vis manager.";
|
||||
if (fNKeepTheEventRequests == 0) {
|
||||
G4warn <<
|
||||
"\n The kept events are those you have asked to be kept in your user action(s).)";
|
||||
"\n The kept events are those you have asked to be kept in your user action(s).";
|
||||
} else {
|
||||
G4warn <<
|
||||
"\n The same or further events may have been kept by you in your user action(s).)";
|
||||
"\n The same or further events may have been kept by you in your user action(s)."
|
||||
"\n To turn off event keeping by the vis manager: /vis/drawOnlyToBeKeptEvents"
|
||||
"\n or use /vis/scene/endOfEventAction <refresh|accumulate> 0";
|
||||
}
|
||||
G4warn << G4endl;
|
||||
}
|
||||
@@ -2491,39 +2417,32 @@ void G4VisManager::EndOfRun ()
|
||||
}
|
||||
}
|
||||
|
||||
// Don't call IsValidView unless there is a scene handler. This
|
||||
// avoids WARNING message at end of event and run when the user has
|
||||
// not instantiated a scene handler, e.g., in batch mode.
|
||||
G4bool valid = fpSceneHandler && IsValidView();
|
||||
if (GetConcreteInstance() && valid) {
|
||||
// // ???? I can't remember why
|
||||
// // if (!fpSceneHandler->GetMarkForClearingTransientStore()) {
|
||||
// // is here. It prevents ShowView at end of run, which seems to be OK
|
||||
// // for sequential mode, but MT mode seems to need it (I have not
|
||||
// // figured out why). ???? JA ????
|
||||
// if (!fpSceneHandler->GetMarkForClearingTransientStore()) {
|
||||
if (fpScene->GetRefreshAtEndOfRun()) {
|
||||
fpSceneHandler->DrawEndOfRunModels();
|
||||
// An extra refresh for auto-refresh viewers.
|
||||
// ???? I DON'T WHY THIS IS NECESSARY ???? JA ????
|
||||
if (fpViewer->GetViewParameters().IsAutoRefresh()) {
|
||||
fpViewer->RefreshView();
|
||||
}
|
||||
// ShowView guarantees the view is flushed to the screen. It also
|
||||
// triggers other features such picking (if enabled) and allows
|
||||
// file-writing viewers to close the file.
|
||||
fpViewer->ShowView();
|
||||
fpSceneHandler->SetMarkForClearingTransientStore(true);
|
||||
} else {
|
||||
if (fpGraphicsSystem->GetFunctionality() ==
|
||||
G4VGraphicsSystem::fileWriter) {
|
||||
if (fVerbosity >= warnings) {
|
||||
G4warn << "\"/vis/viewer/update\" to close file." << G4endl;
|
||||
}
|
||||
}
|
||||
if (fpScene->GetRefreshAtEndOfRun()) {
|
||||
fpSceneHandler->DrawEndOfRunModels();
|
||||
// An extra refresh for auto-refresh viewers.
|
||||
// ???? I DON'T WHY THIS IS NECESSARY ???? JA ????
|
||||
if (fpViewer->GetViewParameters().IsAutoRefresh()) {
|
||||
fpViewer->RefreshView();
|
||||
}
|
||||
// ShowView guarantees the view is flushed to the screen. It also
|
||||
// triggers other features such picking (if enabled) and allows
|
||||
// file-writing viewers to close the file.
|
||||
fpViewer->ShowView();
|
||||
fpSceneHandler->SetMarkForClearingTransientStore(true);
|
||||
} else {
|
||||
if (fpGraphicsSystem->GetFunctionality() ==
|
||||
G4VGraphicsSystem::fileWriter) {
|
||||
if (fVerbosity >= warnings) {
|
||||
G4warn << "\"/vis/viewer/update\" to close file." << G4endl;
|
||||
}
|
||||
// }
|
||||
}
|
||||
}
|
||||
//}
|
||||
fEventRefreshing = false;
|
||||
}
|
||||
|
||||
@@ -2554,7 +2473,7 @@ void G4VisManager::ResetTransientsDrawnFlags()
|
||||
}
|
||||
|
||||
G4String G4VisManager::ViewerShortName (const G4String& viewerName) const {
|
||||
G4String viewerShortName = viewerName.substr(0, viewerName.find (' '));
|
||||
const G4String& viewerShortName = viewerName.substr(0, viewerName.find (' '));
|
||||
return G4StrUtil::strip_copy(viewerShortName);
|
||||
}
|
||||
|
||||
@@ -2596,9 +2515,19 @@ G4String G4VisManager::VerbosityString(Verbosity verbosity) {
|
||||
return rs;
|
||||
}
|
||||
|
||||
void G4VisManager::PrintAvailableVerbosity(std::ostream& os)
|
||||
{
|
||||
os << "Available verbosity options:";
|
||||
for (std::size_t i = 0; i < VerbosityGuidanceStrings.size(); ++i) {
|
||||
os << '\n' << VerbosityGuidanceStrings[i];
|
||||
}
|
||||
os << "\nCurrent verbosity: " << G4VisManager::VerbosityString(fVerbosity);
|
||||
os << std::endl;
|
||||
}
|
||||
|
||||
G4VisManager::Verbosity
|
||||
G4VisManager::GetVerbosityValue(const G4String& verbosityString) {
|
||||
G4String ss = G4StrUtil::to_lower_copy(verbosityString);
|
||||
G4String ss = G4StrUtil::to_lower_copy(verbosityString);
|
||||
Verbosity verbosity;
|
||||
if (ss[0] == 'q') verbosity = quiet;
|
||||
else if (ss[0] == 's') verbosity = startup;
|
||||
@@ -2608,18 +2537,16 @@ G4VisManager::GetVerbosityValue(const G4String& verbosityString) {
|
||||
else if (ss[0] == 'p') verbosity = parameters;
|
||||
else if (ss[0] == 'a') verbosity = all;
|
||||
else {
|
||||
// Could be an integer
|
||||
G4int intVerbosity;
|
||||
std::istringstream is(ss);
|
||||
is >> intVerbosity;
|
||||
if (!is) {
|
||||
G4warn << "ERROR: G4VisManager::GetVerbosityValue: invalid verbosity \""
|
||||
<< verbosityString << "\"";
|
||||
for (std::size_t i = 0; i < VerbosityGuidanceStrings.size(); ++i) {
|
||||
G4warn << '\n' << VerbosityGuidanceStrings[i];
|
||||
}
|
||||
verbosity = warnings;
|
||||
G4warn << "\n Returning " << VerbosityString(verbosity)
|
||||
<< G4endl;
|
||||
<< verbosityString << "\"\n";
|
||||
PrintAvailableVerbosity(G4warn);
|
||||
// Return existing verbosity
|
||||
return fVerbosity;
|
||||
}
|
||||
else {
|
||||
verbosity = GetVerbosityValue(intVerbosity);
|
||||
@@ -2767,12 +2694,13 @@ G4VisManager::RegisterModelFactories()
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef G4MULTITHREADED
|
||||
void G4VisManager::SetUpForAThread()
|
||||
{
|
||||
// TODO: protect with G4Threading::IsMultithreadedApplication() instead?
|
||||
#ifdef G4MULTITHREADED
|
||||
new G4VisStateDependent(this);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void G4VisManager::IgnoreStateChanges(G4bool val)
|
||||
{
|
||||
|
||||
@@ -6,6 +6,21 @@ It must **not** be used as a substitute for writing good git commit messages!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## 2024-10-22 John Allison (modeling-V11-02-05)
|
||||
- G4PhysicalVolumeModel.cc:
|
||||
- Fixed some ragged indentations.
|
||||
|
||||
## 2024-10-16 John Allison (modeling-V11-02-04)
|
||||
- G4TrajectoryDrawByEncounteredVolume.cc, G4TrajectoryEncounteredVolumeFilter.cc:
|
||||
- Replace check on trajectory type using dynamic_cast with a simple check
|
||||
on the existence on the required G4Att.
|
||||
|
||||
## 2024-08-31 John Allison (modeling-V11-02-03)
|
||||
- More Coverity fixes
|
||||
|
||||
## 2024-07-17 John Allison (modeling-V11-02-02)
|
||||
- Coverity fixes
|
||||
|
||||
## 2024-01-22 John Allison (modeling-V11-02-01)
|
||||
- Coworks with visman-V11-02-04, greps-V11-02-00 and interfaces-V11-02-01.
|
||||
- G4PhysicalVolumeModel:
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
#include "G4ConversionFatalError.hh"
|
||||
#include "G4ConversionUtils.hh"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace {
|
||||
|
||||
// Helper classes
|
||||
@@ -168,8 +170,7 @@ G4AttValueFilterT<T, ConversionErrorPolicy>::LoadIntervalElement(const G4String&
|
||||
|
||||
if (!G4ConversionUtils::Convert(input, min, max)) ConversionErrorPolicy::ReportError(input, "Invalid format. Was the input data formatted correctly ?");
|
||||
|
||||
std::pair<T, T> myPair(min, max);
|
||||
fIntervalMap[input] = myPair;
|
||||
fIntervalMap[input] = std::pair<T, T> (min, max);
|
||||
}
|
||||
|
||||
template <typename T, typename ConversionErrorPolicy>
|
||||
@@ -180,7 +181,7 @@ G4AttValueFilterT<T, ConversionErrorPolicy>::LoadSingleValueElement(const G4Stri
|
||||
|
||||
if (!G4ConversionUtils::Convert(input, output)) ConversionErrorPolicy::ReportError(input, "Invalid format. Was the input data formatted correctly ?");
|
||||
|
||||
fSingleValueMap[input] = output;
|
||||
fSingleValueMap[input] = std::move(output);
|
||||
}
|
||||
|
||||
template <typename T, typename ConversionErrorPolicy>
|
||||
|
||||
@@ -37,7 +37,9 @@
|
||||
#include "G4AttValue.hh"
|
||||
#include "G4SmartFilter.hh"
|
||||
#include "G4VAttValueFilter.hh"
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
template <typename T>
|
||||
class G4AttributeFilterT : public G4SmartFilter<T> {
|
||||
@@ -208,7 +210,7 @@ G4AttributeFilterT<T>::AddInterval(const G4String& interval)
|
||||
return;
|
||||
}
|
||||
|
||||
fConfigVect.push_back(myPair);
|
||||
fConfigVect.push_back(std::move(myPair));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -226,7 +228,7 @@ G4AttributeFilterT<T>::AddValue(const G4String& value)
|
||||
("G4AttributeFilterT::AddValue", "modeling0105", JustWarning, ed);
|
||||
return;
|
||||
}
|
||||
fConfigVect.push_back(myPair);
|
||||
fConfigVect.push_back(std::move(myPair));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -86,7 +86,7 @@ public: // With description
|
||||
class PVNameCopyNo {
|
||||
public:
|
||||
// Normal constructor
|
||||
PVNameCopyNo(G4String name, G4int copyNo)
|
||||
PVNameCopyNo(const G4String& name, G4int copyNo)
|
||||
: fName(name), fCopyNo(copyNo) {}
|
||||
const G4String& GetName() const {return fName;}
|
||||
G4int GetCopyNo() const {return fCopyNo;}
|
||||
|
||||
@@ -61,13 +61,11 @@ public:
|
||||
G4VPhysicalVolume* pFoundPV,
|
||||
G4int foundPVCopyNo = 0,
|
||||
G4int foundDepth = 0,
|
||||
std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>
|
||||
foundBasePVPath =
|
||||
std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>(),
|
||||
std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>
|
||||
foundFullPVPath =
|
||||
std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>(),
|
||||
G4Transform3D foundObjectTransformation = G4Transform3D())
|
||||
const std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>&
|
||||
foundBasePVPath = std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>(),
|
||||
const std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>&
|
||||
foundFullPVPath = std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>(),
|
||||
const G4Transform3D& foundObjectTransformation = G4Transform3D())
|
||||
: fpSearchPV(pSearchPV)
|
||||
, fpFoundPV(pFoundPV)
|
||||
, fFoundPVCopyNo(foundPVCopyNo)
|
||||
|
||||
@@ -305,18 +305,18 @@ void G4PhysicalVolumeModel::VisitGeometryAndGetVisReps
|
||||
G4VPVParameterisation* pP = pVPV -> GetParameterisation ();
|
||||
if (pP) { // Parametrised volume.
|
||||
for (int n = nBegin; n < nEnd; n++) {
|
||||
pSol = pP -> ComputeSolid (n, pVPV);
|
||||
pP -> ComputeTransformation (n, pVPV);
|
||||
pSol -> ComputeDimensions (pP, n, pVPV);
|
||||
pVPV -> SetCopyNo (n);
|
||||
pSol = pP -> ComputeSolid (n, pVPV);
|
||||
pP -> ComputeTransformation (n, pVPV);
|
||||
pSol -> ComputeDimensions (pP, n, pVPV);
|
||||
pVPV -> SetCopyNo (n);
|
||||
fCurrentPVCopyNo = n;
|
||||
// Create a touchable of current parent for ComputeMaterial.
|
||||
// fFullPVPath has not been updated yet so at this point it
|
||||
// corresponds to the parent.
|
||||
G4PhysicalVolumeModelTouchable parentTouchable(fFullPVPath);
|
||||
pMaterial = pP -> ComputeMaterial (n, pVPV, &parentTouchable);
|
||||
DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial,
|
||||
theAT, sceneHandler);
|
||||
// Create a touchable of current parent for ComputeMaterial.
|
||||
// fFullPVPath has not been updated yet so at this point it
|
||||
// corresponds to the parent.
|
||||
G4PhysicalVolumeModelTouchable parentTouchable(fFullPVPath);
|
||||
pMaterial = pP -> ComputeMaterial (n, pVPV, &parentTouchable);
|
||||
DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial,
|
||||
theAT, sceneHandler);
|
||||
}
|
||||
}
|
||||
else { // Plain replicated volume. From geometry_guide.txt...
|
||||
@@ -347,64 +347,64 @@ void G4PhysicalVolumeModel::VisitGeometryAndGetVisReps
|
||||
G4RotationMatrix* pOriginalRotation = pVPV -> GetRotation ();
|
||||
G4double originalRMin = 0., originalRMax = 0.;
|
||||
if (axis == kRho && pSol->GetEntityType() == "G4Tubs") {
|
||||
originalRMin = ((G4Tubs*)pSol)->GetInnerRadius();
|
||||
originalRMax = ((G4Tubs*)pSol)->GetOuterRadius();
|
||||
originalRMin = ((G4Tubs*)pSol)->GetInnerRadius();
|
||||
originalRMax = ((G4Tubs*)pSol)->GetOuterRadius();
|
||||
}
|
||||
G4bool visualisable = true;
|
||||
for (int n = nBegin; n < nEnd; n++) {
|
||||
G4ThreeVector translation; // Identity.
|
||||
G4RotationMatrix rotation; // Identity - life enough for visualizing.
|
||||
G4RotationMatrix* pRotation = 0;
|
||||
switch (axis) {
|
||||
default:
|
||||
case kXAxis:
|
||||
translation = G4ThreeVector (-width*(nReplicas-1)*0.5+n*width,0,0);
|
||||
break;
|
||||
case kYAxis:
|
||||
translation = G4ThreeVector (0,-width*(nReplicas-1)*0.5+n*width,0);
|
||||
break;
|
||||
case kZAxis:
|
||||
translation = G4ThreeVector (0,0,-width*(nReplicas-1)*0.5+n*width);
|
||||
break;
|
||||
case kRho:
|
||||
if (pSol->GetEntityType() == "G4Tubs") {
|
||||
((G4Tubs*)pSol)->SetInnerRadius(width*n+offset);
|
||||
((G4Tubs*)pSol)->SetOuterRadius(width*(n+1)+offset);
|
||||
} else {
|
||||
if (fpMP->IsWarning())
|
||||
G4warn <<
|
||||
"G4PhysicalVolumeModel::VisitGeometryAndGetVisReps: WARNING:"
|
||||
"\n built-in replicated volumes replicated in radius for "
|
||||
<< pSol->GetEntityType() <<
|
||||
"-type\n solids (your solid \""
|
||||
<< pSol->GetName() <<
|
||||
"\") are not visualisable."
|
||||
<< G4endl;
|
||||
visualisable = false;
|
||||
}
|
||||
break;
|
||||
case kPhi:
|
||||
rotation.rotateZ (-(offset+(n+0.5)*width));
|
||||
// Minus Sign because for the physical volume we need the
|
||||
// coordinate system rotation.
|
||||
pRotation = &rotation;
|
||||
break;
|
||||
}
|
||||
pVPV -> SetTranslation (translation);
|
||||
pVPV -> SetRotation (pRotation);
|
||||
pVPV -> SetCopyNo (n);
|
||||
G4ThreeVector translation; // Identity.
|
||||
G4RotationMatrix rotation; // Identity - life enough for visualizing.
|
||||
G4RotationMatrix* pRotation = 0;
|
||||
switch (axis) {
|
||||
default:
|
||||
case kXAxis:
|
||||
translation = G4ThreeVector (-width*(nReplicas-1)*0.5+n*width,0,0);
|
||||
break;
|
||||
case kYAxis:
|
||||
translation = G4ThreeVector (0,-width*(nReplicas-1)*0.5+n*width,0);
|
||||
break;
|
||||
case kZAxis:
|
||||
translation = G4ThreeVector (0,0,-width*(nReplicas-1)*0.5+n*width);
|
||||
break;
|
||||
case kRho:
|
||||
if (pSol->GetEntityType() == "G4Tubs") {
|
||||
((G4Tubs*)pSol)->SetInnerRadius(width*n+offset);
|
||||
((G4Tubs*)pSol)->SetOuterRadius(width*(n+1)+offset);
|
||||
} else {
|
||||
if (fpMP->IsWarning())
|
||||
G4warn <<
|
||||
"G4PhysicalVolumeModel::VisitGeometryAndGetVisReps: WARNING:"
|
||||
"\n built-in replicated volumes replicated in radius for "
|
||||
<< pSol->GetEntityType() <<
|
||||
"-type\n solids (your solid \""
|
||||
<< pSol->GetName() <<
|
||||
"\") are not visualisable."
|
||||
<< G4endl;
|
||||
visualisable = false;
|
||||
}
|
||||
break;
|
||||
case kPhi:
|
||||
rotation.rotateZ (-(offset+(n+0.5)*width));
|
||||
// Minus Sign because for the physical volume we need the
|
||||
// coordinate system rotation.
|
||||
pRotation = &rotation;
|
||||
break;
|
||||
}
|
||||
pVPV -> SetTranslation (translation);
|
||||
pVPV -> SetRotation (pRotation);
|
||||
pVPV -> SetCopyNo (n);
|
||||
fCurrentPVCopyNo = n;
|
||||
if (visualisable) {
|
||||
DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial,
|
||||
theAT, sceneHandler);
|
||||
}
|
||||
if (visualisable) {
|
||||
DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial,
|
||||
theAT, sceneHandler);
|
||||
}
|
||||
}
|
||||
// Restore originals...
|
||||
pVPV -> SetTranslation (originalTranslation);
|
||||
pVPV -> SetRotation (pOriginalRotation);
|
||||
if (axis == kRho && pSol->GetEntityType() == "G4Tubs") {
|
||||
((G4Tubs*)pSol)->SetInnerRadius(originalRMin);
|
||||
((G4Tubs*)pSol)->SetOuterRadius(originalRMax);
|
||||
((G4Tubs*)pSol)->SetInnerRadius(originalRMin);
|
||||
((G4Tubs*)pSol)->SetOuterRadius(originalRMax);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
#include "G4VTrajectory.hh"
|
||||
#include "G4VisTrajContext.hh"
|
||||
#include "G4VTrajectoryPoint.hh"
|
||||
#include "G4AttDef.hh"
|
||||
#include "G4AttValue.hh"
|
||||
#include "G4RichTrajectory.hh"
|
||||
|
||||
G4TrajectoryDrawByEncounteredVolume::G4TrajectoryDrawByEncounteredVolume
|
||||
(const G4String& name, G4VisTrajContext* context)
|
||||
@@ -46,9 +46,12 @@ G4TrajectoryDrawByEncounteredVolume::~G4TrajectoryDrawByEncounteredVolume() {}
|
||||
void
|
||||
G4TrajectoryDrawByEncounteredVolume::Draw(const G4VTrajectory& traj, const G4bool& /*visible*/) const
|
||||
{
|
||||
try
|
||||
{
|
||||
const G4RichTrajectory& richTrajectory = dynamic_cast<const G4RichTrajectory&>(traj);
|
||||
// Check the required G4Att exists
|
||||
const auto& aPointAttDefs = traj.GetPoint(0)->GetAttDefs();
|
||||
if (aPointAttDefs->find("PostVPath") != aPointAttDefs->end()) {
|
||||
|
||||
// Must be a rich trajectory
|
||||
const auto& richTrajectory = traj;
|
||||
|
||||
G4Colour colour(fDefault);
|
||||
G4String soughtPVName("none");
|
||||
@@ -82,20 +85,18 @@ G4TrajectoryDrawByEncounteredVolume::Draw(const G4VTrajectory& traj, const G4boo
|
||||
<< ", with configuration:" << G4endl;
|
||||
myContext.Print(G4cout);
|
||||
}
|
||||
|
||||
G4TrajectoryDrawerUtils::DrawLineAndPoints(richTrajectory, myContext);
|
||||
|
||||
}
|
||||
|
||||
catch (const std::bad_cast&)
|
||||
{
|
||||
G4TrajectoryDrawerUtils::DrawLineAndPoints(richTrajectory, myContext);
|
||||
|
||||
} else {
|
||||
|
||||
G4ExceptionDescription ed;
|
||||
ed << "Requires G4RichTrajectory - \"/vis/scene/add/trajectories rich\"";
|
||||
G4Exception
|
||||
("G4TrajectoryDrawByEncounteredVolume::Draw(const G4VTrajectory& traj,...",
|
||||
"modeling0125",
|
||||
JustWarning, ed);
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
#include "G4UIcommand.hh"
|
||||
#include "G4AttValue.hh"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#define G4warn G4cout
|
||||
|
||||
namespace G4TrajectoryDrawerUtils {
|
||||
@@ -203,8 +205,8 @@ namespace G4TrajectoryDrawerUtils {
|
||||
}
|
||||
}
|
||||
|
||||
trajectoryLine = newTrajectoryLine;
|
||||
trajectoryLineTimes = newTrajectoryLineTimes;
|
||||
trajectoryLine = std::move(newTrajectoryLine);
|
||||
trajectoryLineTimes = std::move(newTrajectoryLineTimes);
|
||||
}
|
||||
|
||||
static void DrawWithoutTime(const G4VisTrajContext& myContext,
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
#include "G4TrajectoryEncounteredVolumeFilter.hh"
|
||||
#include "G4TransportationManager.hh"
|
||||
#include "G4VTrajectoryPoint.hh"
|
||||
#include "G4AttDef.hh"
|
||||
#include "G4AttValue.hh"
|
||||
#include "G4RichTrajectory.hh"
|
||||
|
||||
G4TrajectoryEncounteredVolumeFilter::G4TrajectoryEncounteredVolumeFilter(const G4String& name)
|
||||
:G4SmartFilter<G4VTrajectory>(name)
|
||||
@@ -44,10 +44,13 @@ G4TrajectoryEncounteredVolumeFilter::~G4TrajectoryEncounteredVolumeFilter() {}
|
||||
bool
|
||||
G4TrajectoryEncounteredVolumeFilter::Evaluate(const G4VTrajectory& traj) const
|
||||
{
|
||||
try
|
||||
{
|
||||
const G4RichTrajectory& richTrajectory = dynamic_cast<const G4RichTrajectory&>(traj);
|
||||
|
||||
// Check the required G4Att exists
|
||||
const auto& aPointAttDefs = traj.GetPoint(0)->GetAttDefs();
|
||||
if (aPointAttDefs->find("PostVPath") != aPointAttDefs->end()) {
|
||||
|
||||
// Must be a rich trajectory
|
||||
const auto& richTrajectory = traj;
|
||||
|
||||
for (const auto& pvname: fVolumes) {
|
||||
for (G4int iPoint = 0; iPoint < richTrajectory.GetPointEntries(); iPoint++) {
|
||||
G4VTrajectoryPoint* point = richTrajectory.GetPoint(iPoint);
|
||||
@@ -64,10 +67,9 @@ G4TrajectoryEncounteredVolumeFilter::Evaluate(const G4VTrajectory& traj) const
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
catch (const std::bad_cast&)
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
G4ExceptionDescription ed;
|
||||
ed << "Requires G4RichTrajectory - \"/vis/scene/add/trajectories rich\"";
|
||||
G4Exception
|
||||
@@ -75,6 +77,7 @@ G4TrajectoryEncounteredVolumeFilter::Evaluate(const G4VTrajectory& traj) const
|
||||
"modeling0126",
|
||||
JustWarning, ed);
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user