diff --git a/GeoModelVisualization/VP1Base/VP1Base/IVP13DStandardChannelWidget.h b/GeoModelVisualization/VP1Base/VP1Base/IVP13DStandardChannelWidget.h
index d65b4b713bfb689e9d5b1fca9fc4ea47cb7044b7..22c51305c1e699ae70cc455b1df58d48488ece3f 100644
--- a/GeoModelVisualization/VP1Base/VP1Base/IVP13DStandardChannelWidget.h
+++ b/GeoModelVisualization/VP1Base/VP1Base/IVP13DStandardChannelWidget.h
@@ -16,6 +16,9 @@
 #define IVP13DSTANDARDCHANNELWIDGET_H
 
 #include "VP1Base/IVP13DChannelWidget.h"
+
+
+// FWD declarations
 class IVP13DSystem;
 class IVP13DSystemSimple;
 class QResizeEvent;
@@ -74,6 +77,7 @@ private slots:
   void toggleSystemActive();
   void updateSnapshotDim();
   void setImageFromPresets();
+  void updateTransparencyType(unsigned type);
 
 protected slots:
   void showControlsForSystem();
diff --git a/GeoModelVisualization/VP1Base/VP1Base/VP1Msg.h b/GeoModelVisualization/VP1Base/VP1Base/VP1Msg.h
index 0f72e1ada0a3e5707448cc6fc099a1c179e19f3c..81ba888e176edd30eb5728a3551f9b496bae9456 100644
--- a/GeoModelVisualization/VP1Base/VP1Base/VP1Msg.h
+++ b/GeoModelVisualization/VP1Base/VP1Base/VP1Msg.h
@@ -30,6 +30,8 @@ class VP1Msg : public VP1String {
 public:
   static bool verbose() { return m_verbose; } // Returns true if env var VP1_VERBOSE_OUTPUT=1
   static bool debug() { return m_debug; } // Returns true if env var VP1_DEBUG_OUTPUT=1
+  static bool debug2() { return m_debug_2; } // Returns true if env var VP1_DEBUG_2_OUTPUT=1
+  static bool debug3() { return m_debug_3; } // Returns true if env var VP1_DEBUG_3_OUTPUT=1
 
   #if defined BUILDVP1LIGHT
     static void enableMsg(const QString&, const QString&);  
@@ -39,6 +41,8 @@ public:
 
   static void message(const QString&, IVP1System*sys = 0);//Non-zero sys pointer to get message in GUI
   static void messageDebug(const QString&);
+  static void messageDebug2(const QString&);
+  static void messageDebug3(const QString&); 
   static void messageWarning(const QString&);
   static void messageVerbose(const QString&);//This outputs only if verbose() is true.
   static void messageWarningRed( const QString& str );
@@ -54,6 +58,8 @@ public:
 
   static const char* prefix_msg() { return "VP1MESSAGE";}
   static const char* prefix_debug() { return "VP1MSG_DEBUG";}
+  static const char* prefix_debug2() { return "VP1MSG_DEBUG_2";}
+  static const char* prefix_debug3() { return "VP1MSG_DEBUG_3";}
   static const char* prefix_warning() { return "VP1MSG_WARNING";}
   static const char* prefix_verbose() { return "VP1MSG_VERBOSE";}
 
@@ -62,6 +68,8 @@ private:
   ~VP1Msg(){}
   static bool m_verbose;
   static bool m_debug;
+  static bool m_debug_2;
+  static bool m_debug_3;
 };
 
 #endif
diff --git a/GeoModelVisualization/VP1Base/src/IVP13DStandardChannelWidget.cxx b/GeoModelVisualization/VP1Base/src/IVP13DStandardChannelWidget.cxx
index 24b262f2f1353b8d2bfa33f33ed1da051e999fcb..bc968161ba228ed4ee8886808f374ecf068f177b 100644
--- a/GeoModelVisualization/VP1Base/src/IVP13DStandardChannelWidget.cxx
+++ b/GeoModelVisualization/VP1Base/src/IVP13DStandardChannelWidget.cxx
@@ -30,6 +30,7 @@
 #include <Inventor/actions/SoBoxHighlightRenderAction.h>
 #include <Inventor/nodes/SoPerspectiveCamera.h>
 #include <Inventor/SoOffscreenRenderer.h>
+#include <Inventor/actions/SoGLRenderAction.h>
 
 #include <QSplitter>
 #include <QVBoxLayout>
@@ -252,12 +253,22 @@ void IVP13DStandardChannelWidget::create() {
   m_d->viewer->setTransparencyType( SoGLRenderAction::BLEND ); // this looks better for geometry volumes
 
   //Setup camera info:
-  foreach(IVP13DSystem*sys,m_d->systemsAllowedCameraList)
+  foreach(IVP13DSystem*sys,m_d->systemsAllowedCameraList) {
     sys->registerViewer(m_d->viewer);
+    connect(sys,SIGNAL(updateTransparencyType(unsigned)), this,SLOT(updateTransparencyType(unsigned)));
+  }
 
   snapshotgroupbox->hide();
 }
 
+
+//___________________________________________________________________________
+void IVP13DStandardChannelWidget::updateTransparencyType(unsigned type)
+{
+  //if( VP1Msg::debug())
+      //std::cout << "Changing global transparency type to: " << type << std::endl;
+  m_d->viewer->setTransparencyType( VP1QtInventorUtils::intToTransparencyType(type) );
+}
 //___________________________________________________________________________
 void IVP13DStandardChannelWidget::Imp::setupSplitter(QWidget * rightwidget)
 {
diff --git a/GeoModelVisualization/VP1Base/src/VP1Msg.cxx b/GeoModelVisualization/VP1Base/src/VP1Msg.cxx
index 4afb2e5ddd4b7cd8c6f6ae7602e6b5aa4e5eccfb..59629a742d93f34c3999f58023d90d58381c6d08 100644
--- a/GeoModelVisualization/VP1Base/src/VP1Msg.cxx
+++ b/GeoModelVisualization/VP1Base/src/VP1Msg.cxx
@@ -20,6 +20,8 @@
 #ifndef BUILDVP1LIGHT   //TODO: Merge the two mechanisms, specifically for VP1
   bool VP1Msg::m_verbose = VP1QtUtils::environmentVariableIsOn("VP1_VERBOSE_OUTPUT");
   bool VP1Msg::m_debug = VP1QtUtils::environmentVariableIsOn("VP1_DEBUG_OUTPUT");
+  bool VP1Msg::m_debug_2 = VP1QtUtils::environmentVariableIsOn("VP1_DEBUG_2_OUTPUT");
+  bool VP1Msg::m_debug_3 = VP1QtUtils::environmentVariableIsOn("VP1_DEBUG_3_OUTPUT");
 #endif
 #ifdef BUILDVP1LIGHT
   bool VP1Msg::m_verbose = VP1QtUtils::expertSettingIsSet("general", "ExpertSettings/VP1_VERBOSE_OUTPUT");
@@ -38,12 +40,31 @@ void VP1Msg::message( const QString& str, IVP1System*sys )
 //____________________________________________________________________
 void VP1Msg::messageDebug( const QString& str )
 {
-  if (!debug()){
+  if ( ! (debug() or debug2() or debug3()) ){
     return;
   }
   std::cout << "DBG!!!" << prefix_debug() << ": "<< str.toStdString()<<std::endl;
 }
 
+//____________________________________________________________________
+void VP1Msg::messageDebug2( const QString& str )
+{
+  if ( ! (debug2() or debug3()) ){
+    return;
+  }
+  std::cout << prefix_debug2() << ": "<< str.toStdString()<<std::endl;
+}
+
+//____________________________________________________________________
+void VP1Msg::messageDebug3( const QString& str )
+{
+  if (!debug3()){
+    return;
+  }
+  std::cout << prefix_debug3() << ": "<< str.toStdString()<<std::endl;
+}
+
+
 //____________________________________________________________________
 void VP1Msg::messageWarning( const QString& str )
 {
diff --git a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/GeoSysController.h b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/GeoSysController.h
index 7133772b3475d518dba4f1fa3a583eb15ad1e668..4fc0a1e7827e48d8072182a7f7706be7455492fe 100644
--- a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/GeoSysController.h
+++ b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/GeoSysController.h
@@ -1,17 +1,22 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
 */
 
 
 ////////////////////////////////////////////////////////////////
-//                                                            //
-//  Header file for class GeoSysController                    //
-//                                                            //
-//  Description: Controller for the geometry system.          //
-//                                                            //
-//  Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch)  //
-//  Initial version: October 2008                             //
-//                                                            //
+//                                                            
+//  Header file for class GeoSysController                    
+//                                                            
+//  Description: Controller for the geometry system.          
+//                                                            
+//  Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch)  
+//  Initial version: October 2008                             
+//
+//  Major updates:
+//   
+//  - Riccardo Maria BIANCHI (riccardo.maria.bianchi@cern.ch)  
+//    Jul 2021: Added support to filter volumes based on names
+//
 ////////////////////////////////////////////////////////////////
 
 #ifndef GEOSYSCONTROLLER_H
@@ -75,6 +80,9 @@ public:
   //Settings with change signals:
 
   float transparency() const;
+  void setTransparency(float value) const;
+  bool isTranspLocked() const;
+
   bool showVolumeOutLines() const;
   int labels() const;
   QList<int> labelPosOffset() ; //!< Offset in x,y,z
@@ -90,10 +98,10 @@ signals:
 
   //Signals without state:
   void resetSubSystems(VP1GeoFlags::SubSystemFlag);
-  void autoExpandByVolumeOrMaterialName(bool,QString);//volname: (false,namestr), matname: (true,namestr)
+  void autoExpandByVolumeOrMaterialName(bool, QString); //volname: (false,namestr), matname: (true,namestr)
   void volumeStateChangeRequested(VolumeHandle*,VP1GeoFlags::VOLSTATE);//Might not be used atm.
   void volumeResetRequested(VolumeHandle*);
-
+  void signalFilterVolumes(QString, bool, int, bool, bool, bool);
   void saveMaterialsToFile(QString,bool);//(filename,onlyChangedMaterials)
   void loadMaterialsFromFile(QString);//filename
   void displayLocalAxesChanged(int);
@@ -112,7 +120,6 @@ private slots:
   void saveMaterialsRequested();
   void loadMaterialsRequested();
   void emit_autoExpandByVolumeOrMaterialName();
-  // void emit_actionOnAllNonStandardVolumes(); // not used anymore?
 };
 
 #endif
diff --git a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VP1GeometrySystem.h b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VP1GeometrySystem.h
index 9d100b53915eefc30113cc25887cc3f640f4d23b..e33dda7102b53f93f496c4e0e7c259023a26db82 100644
--- a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VP1GeometrySystem.h
+++ b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VP1GeometrySystem.h
@@ -6,26 +6,35 @@
 #define VP1GEOMETRYSYSTEM_H
 
 /////////////////////////////////////////////////////////////////////////
-//                                                                     //
-//  Header file for class VP1GeometrySystem                            //
-//                                                                     //
-//  Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch>              //
-//                                                                     //
-//  Derived from V-atlas geometry system by Joe Boudreau.              //
-//  Origins of initial version dates back to ~1996, initial VP1        //
-//  version by TK (May 2007) and almost entirely rewritten Oct 2007    //
-//                                                                     //
+//                                                                     
+//  Header file for class VP1GeometrySystem                            
+//                                                                     
+//  Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch>              
+//                                                                     
+//  Derived from V-atlas geometry system by Joe Boudreau.              
+//  Origins of initial version dates back to ~1996, initial VP1        
+//  version by TK (May 2007) and almost entirely rewritten Oct 2007
+//
+//  - Jul 2021, Riccardo Maria Bianchi <riccardo.maria.bianchi@cern.ch>
+//              * Added the 'filter volumes' tool
+//              * Added signal/slot to update transparency type in the 3D window
+//                                                                     
 /////////////////////////////////////////////////////////////////////////
 
 #include "VP1Base/IVP13DSystemSimple.h"
 #include "VP1GeometrySystems/VP1GeoFlags.h"
 #include "VP1GeometrySystems/VolumeHandle.h"//fixme
+
 #include "GeoModelKernel/GeoPhysVol.h"
+
 #include <set>
 #include <map>
 #include <QStack>
 #include <QString>
 
+
+
+
 class VP1GeometrySystem : public IVP13DSystemSimple {
 
   Q_OBJECT
@@ -52,6 +61,9 @@ public:
   QByteArray saveState();
   void restoreFromState(QByteArray);
 
+signals:
+  void updateTransparencyType(unsigned type);
+
 public slots:
 
   void setCurvedSurfaceRealism(int);//Accepts values in the range 0..100.
@@ -60,10 +72,14 @@ protected slots:
   void updateTransparency();
 
   void resetSubSystems(VP1GeoFlags::SubSystemFlags);
-  void autoExpandByVolumeOrMaterialName(bool,QString);//volname: (false,namestr), matname: (true,namestr)
+  void autoExpandByVolumeOrMaterialName(bool, QString);//volname: (false,namestr), matname: (true,namestr)
+
+  void volumeStateChangeRequested(VolumeHandle*,VP1GeoFlags::VOLSTATE);
+  void volumeResetRequested(VolumeHandle*);
 
-  // void volumeStateChangeRequested(VolumeHandle*,VP1GeoFlags::VOLSTATE); // not used anymore?
-  // void volumeResetRequested(VolumeHandle*); // not used anymore?
+  void actionOnAllNonStandardVolumes(bool);//true: zap, false: expand.
+  void actionOnAllVolumes(bool zap, bool standardVolumes = true);//true: zap, false: expand; true: standardVolumes
+  void filterVolumes(QString targetname, bool bymatname, int maxDepth, bool stopAtFirst, bool visitChildren, bool reset);
 
   void setShowVolumeOutLines(bool);
 
diff --git a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VolumeHandle.h b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VolumeHandle.h
index 10c32872f0ed27fcffdaedce396fa3b2ed091267..082bb56b25041a356eeed17e40194048e22b3813 100644
--- a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VolumeHandle.h
+++ b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VolumeHandle.h
@@ -76,6 +76,7 @@ public:
   bool isEther() const;
   void expandMothersRecursivelyToNonEther();//expands the tree down to volumes that are either not ether or without children
 
+  bool isInitialisedAndHasNonStandardShape() const;//True if the 3D shape of this volume can not be represented by standard VRML nodes.
 
   SoSeparator * nodeSoSeparator() const;//Returns pointer to 3D representation of volume (null if not built yet).
   void ensureBuildNodeSep();
diff --git a/GeoModelVisualization/VP1GeometrySystems/src/GeoSysController.cxx b/GeoModelVisualization/VP1GeometrySystems/src/GeoSysController.cxx
index 5917f02d1c4b257066a6121d3b8655c915541579..d804ce7badbe33e266e8a4d44de51d887d031ab4 100644
--- a/GeoModelVisualization/VP1GeometrySystems/src/GeoSysController.cxx
+++ b/GeoModelVisualization/VP1GeometrySystems/src/GeoSysController.cxx
@@ -1,15 +1,23 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
 */
 
 
 ////////////////////////////////////////////////////////////////
-//                                                            //
-//  Implementation of class GeoSysController                  //
-//                                                            //
-//  Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch)  //
-//  Initial version: October 2008                             //
-//                                                            //
+//                                                           
+//  Implementation of class GeoSysController                  
+//                                                            
+//  Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch)  
+//  Initial version: October 2008
+//  
+//  Major updates:
+// 
+//  - Riccardo Maria BIANCHI (riccardo.maria.bianchi@cern.ch)  
+//    2019
+//
+//  - Riccardo Maria BIANCHI (riccardo.maria.bianchi@cern.ch)  
+//    Jul 2021: Added support to filter volumes based on names
+//                                                            
 ////////////////////////////////////////////////////////////////
 
 #define VP1IMPVARNAME m_d
@@ -47,7 +55,6 @@ public:
   std::map<VP1GeoFlags::SubSystemFlag,QCheckBox*> subSysCheckBoxMap;
   float last_transparency;
   bool last_showVolumeOutLines;
-  //  VP1GeoFlags::MuonChamberAdaptionStyleFlags last_muonChamberAdaptionStyle;
   int last_labels; //!< needed for POSSIBLECHANGE_IMP macro.
   QList<int> last_labelPosOffset; //!< needed for  POSSIBLECHANGE_IMP macro.
   SoPickStyle * pickStyle;
@@ -56,8 +63,6 @@ public:
 
   QString lastSaveMaterialsFile;
   QString lastLoadMaterialsFile;
-  
-//  std::map<QString, QList<QCheckBox*> > labelProvidingSystems; //!< First is name of system, second is list of types of information provided (system stores actual information)
 };
 
 
@@ -77,7 +82,7 @@ GeoSysController::GeoSysController(IVP1System * sys)
   //  m_d->ui_disp.widget_drawOptions->setLineWidthsDisabled();
   m_d->ui_disp.widget_drawOptions->setPointSizesDisabled();
 //   m_d->ui_disp.widget_drawOptions->setBaseLightingDisabled();
-  m_d->ui_disp.widget_drawOptions->setComplexity(0.6);
+  m_d->ui_disp.widget_drawOptions->setComplexity(1.0); // default 'curved surface accuracy' value
 
   m_d->pickStyle = new SoPickStyle;
   m_d->pickStyle->ref();
@@ -119,15 +124,16 @@ GeoSysController::GeoSysController(IVP1System * sys)
   connect(m_d->ui_misc.lineEdit_expand_vols_volname,SIGNAL(returnPressed()),this,SLOT(emit_autoExpandByVolumeOrMaterialName()));
   connect(m_d->ui_misc.pushButton_expand_vols_volname,SIGNAL(clicked()),this,SLOT(emit_autoExpandByVolumeOrMaterialName()));
 
+  // filter volumes
+  connect(m_d->ui_misc.lineEdit_filter_logvolname,SIGNAL(returnPressed()),this,SLOT(emit_autoExpandByVolumeOrMaterialName()));
+  connect(m_d->ui_misc.pushButton_filter_logvolname,SIGNAL(clicked()),this,SLOT(emit_autoExpandByVolumeOrMaterialName()));
+  connect(m_d->ui_misc.pushButton_filter_reset,SIGNAL(clicked()),this,SLOT(emit_autoExpandByVolumeOrMaterialName()));
+
+
   connect(m_d->ui_int.checkBox_localAxes, SIGNAL(stateChanged(int)), this, SIGNAL(displayLocalAxesChanged(int)));
   connect(m_d->ui_int.slider_AxesScale, SIGNAL(valueChanged(int)), this, SIGNAL(axesScaleChanged(int)));
 
-
   setLastSelectedVolume(0);
-
- 
- 
-
 }
 
 //____________________________________________________________________
@@ -334,6 +340,20 @@ float GeoSysController::transparency() const
   return (v>=100?1.0:(v<=0?0.0:v/100.0));
 }
 
+//____________________________________________________________________
+void GeoSysController::setTransparency(float value) const
+{
+  assert( 0. <= value && value <= 100.);
+  m_d->ui_disp.spinBox_transp->setValue(value);
+  return;
+}
+
+//____________________________________________________________________
+bool GeoSysController::isTranspLocked() const
+{
+      return m_d->ui_misc.lockTransp->isChecked();
+}
+
 //____________________________________________________________________
 bool GeoSysController::showVolumeOutLines() const
 {
@@ -344,14 +364,63 @@ bool GeoSysController::showVolumeOutLines() const
 //____________________________________________________________________
 void GeoSysController::emit_autoExpandByVolumeOrMaterialName()
 {
-  bool volname(sender()==m_d->ui_misc.pushButton_expand_vols_volname
-	       ||sender()==m_d->ui_misc.lineEdit_expand_vols_volname);
-  QString name(volname?m_d->ui_misc.lineEdit_expand_vols_volname->text()
-	       :m_d->ui_misc.lineEdit_expand_vols_matname->text());
-  if (name.isEmpty())
-    return;
-  messageVerbose("emitting autoExpandByVolumeOrMaterialName("+str(!volname)+", "+name+")");
-  emit autoExpandByVolumeOrMaterialName(!volname,name);
+  // if we filter on visible objects, then...
+	if (sender()==m_d->ui_misc.pushButton_expand_vols_volname
+			|| sender()==m_d->ui_misc.lineEdit_expand_vols_volname)
+      {
+          // check if a name is set in the 'volume' field
+          bool volname(sender()==m_d->ui_misc.pushButton_expand_vols_volname
+				      ||sender()==m_d->ui_misc.lineEdit_expand_vols_volname);
+
+          // get volume's or material's name
+		      QString name(volname ? m_d->ui_misc.lineEdit_expand_vols_volname->text()
+				      : m_d->ui_misc.lineEdit_expand_vols_matname->text());
+
+          // return if name is empty
+          if (name.isEmpty()) {
+			       return;
+          }
+
+          // emit the signal
+		      messageVerbose("emitting autoExpandByVolumeOrMaterialName("+str(!volname)+", "+name+")");
+		      emit autoExpandByVolumeOrMaterialName(!volname,name);
+	}
+  // if we use the 'filter volumes' feature, then...
+	else if (sender()==m_d->ui_misc.pushButton_filter_logvolname
+			|| sender()==m_d->ui_misc.lineEdit_filter_logvolname
+            || sender()==m_d->ui_misc.pushButton_filter_reset)
+  {
+        // handle as "filter" if was sent by the 'filter volume' field or 'Apply' button...
+        bool filter(sender()==m_d->ui_misc.pushButton_filter_logvolname
+				      || sender()==m_d->ui_misc.lineEdit_filter_logvolname);
+
+        // handle as "reset the view" if sent by the 'reset filters' button...
+        bool resetView(sender()==m_d->ui_misc.pushButton_filter_reset);
+       
+        // get additional options
+        int maxDepth(m_d->ui_misc.spinBox_maxDepth->value()==-1 ? 9999 : m_d->ui_misc.spinBox_maxDepth->value());
+        bool stopAtFirst(m_d->ui_misc.radioButton_StopAtFirst->isChecked() ? true : false );
+        bool visitChildren(m_d->ui_misc.radioButton_DoNotVisitChildren->isChecked() ? false : true);
+
+        bool bymatname = false; // TODO: set this in the UI!
+        QString nameRegEx(m_d->ui_misc.lineEdit_filter_logvolname->text());
+
+        // return if name is empty
+        if (nameRegEx.isEmpty()) {
+			     return;
+        }
+
+        // clear regex if we are resetting the filters
+        if (resetView) {
+            m_d->ui_misc.radioButton_StopAtFirst->setChecked(true);
+            m_d->ui_misc.radioButton_DoNotVisitChildren->setChecked(true);
+            m_d->ui_misc.lineEdit_filter_logvolname->clear();
+        }
+
+        messageDebug("emitting signalFilterVolumes("+nameRegEx + ", " + str(bymatname) + ", " + str(maxDepth) + ", " + str(stopAtFirst)+ ", " + str(visitChildren) + ", " + str(resetView)+")");
+        emit signalFilterVolumes(nameRegEx, bymatname, maxDepth, stopAtFirst, visitChildren, resetView);
+	} 
+	return;
 }
 
 //____________________________________________________________________
diff --git a/GeoModelVisualization/VP1GeometrySystems/src/VP1GeometrySystem.cxx b/GeoModelVisualization/VP1GeometrySystems/src/VP1GeometrySystem.cxx
index 22d13f1607b1ba850dea45c5b4237502fcf59e55..3e97ae23600afe0426ec99427236e4f6ce62a528 100644
--- a/GeoModelVisualization/VP1GeometrySystems/src/VP1GeometrySystem.cxx
+++ b/GeoModelVisualization/VP1GeometrySystems/src/VP1GeometrySystem.cxx
@@ -1,22 +1,25 @@
 /*
-  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
 */
 
 /////////////////////////////////////////////////////////////////////////
-//                                                                     //
-//  Implementation of class VP1GeometrySystem                          //
-//                                                                     //
-//  Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch>              //
-//                                                                     //
-//  Derived from V-atlas geometry system by Joe Boudreau.              //
-//  Origins of initial version dates back to ~1996, initial VP1        //
-//  version by TK (May 2007) and almost entirely rewritten Oct 2007.   //
-//  Major refactoring october 2008.                                    //
-//                                                                     //
-//  Updates:                                                           //
-//  - Aug 2019, Riccardo Maria Bianchi @ CERN                          //
-//  - Aug 2020, Riccardo Maria Bianchi @ CERN                          //
-//                                                                     //
+//                                                                     
+//  Implementation of class VP1GeometrySystem                          
+//                                                                     
+//  Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch>              
+//                                                                     
+//  Derived from V-atlas geometry system by Joe Boudreau.              
+//  Origins of initial version dates back to ~1996, initial VP1        
+//  version by TK (May 2007) and almost entirely rewritten Oct 2007.   
+//  Major refactoring october 2008.                                    
+//                                                                     
+//  Updates:                                                           
+//  - Aug 2019, Riccardo Maria Bianchi @ CERN                          
+//  - Aug 2020, Riccardo Maria Bianchi @ CERN                          
+//  - Jul 2021, Riccardo Maria Bianchi <riccardo.maria.bianchi@cern.ch> 
+//              * Added the 'filter volumes' tool
+//              * Added signal/slot to update transparency type in the 3D window
+//                                                                     
 /////////////////////////////////////////////////////////////////////////
 
 // local includes
@@ -198,7 +201,10 @@ public:
   static void catchKbdState(void *userData, SoEventCallback *CB);
   const SoKeyboardEvent *kbEvent;
 
+  void changeStateOfVisibleNonStandardVolumesRecursively(VolumeHandle*,VP1GeoFlags::VOLSTATE);
+  void changeStateOfAllVolumesRecursively(VolumeHandle*,VP1GeoFlags::VOLSTATE);
   void expandVisibleVolumesRecursively(VolumeHandle*,const QRegExp&,bool bymatname);
+  bool filterVolumesRec(VolumeHandle* vol, QRegExp selregexp, bool bymatname, bool stopAtFirst, bool visitChildren, bool resetView, bool &zapAll, bool &matchFound, unsigned &nFound, int maxIter = 1, unsigned int iter = 0);
 
   SoSeparator* m_textSep;//!< Separator used to hold all visible labels.
 
@@ -295,7 +301,15 @@ QWidget * VP1GeometrySystem::buildController()
   connect(m_d->controller,SIGNAL(loadMaterialsFromFile(QString)),this,SLOT(loadMaterialsFromFile(QString)));
 
   connect(m_d->controller,SIGNAL(transparencyChanged(float)),this,SLOT(updateTransparency()));
+
+  connect (m_d->controller,SIGNAL(volumeStateChangeRequested(VolumeHandle*,VP1GeoFlags::VOLSTATE)), this,SLOT(volumeStateChangeRequested(VolumeHandle*,VP1GeoFlags::VOLSTATE)));
+  connect (m_d->controller,SIGNAL(volumeResetRequested(VolumeHandle*)), this,SLOT(volumeResetRequested(VolumeHandle*)));
+ 
+ 
+  connect(m_d->controller,SIGNAL(actionOnAllNonStandardVolumes(bool)),this,SLOT(actionOnAllNonStandardVolumes(bool)));
   connect(m_d->controller,SIGNAL(autoExpandByVolumeOrMaterialName(bool,QString)),this,SLOT(autoExpandByVolumeOrMaterialName(bool,QString)));
+  connect(m_d->controller,SIGNAL(signalFilterVolumes(QString, bool, int, bool, bool, bool)),this,SLOT(filterVolumes(QString, bool, int, bool, bool, bool)));
+  
   connect(m_d->controller->requestOutputButton(), SIGNAL(clicked()), this, SLOT(saveTrees()));
   connect(m_d->controller,SIGNAL(displayLocalAxesChanged(int)), this, SLOT(toggleLocalAxes(int)));
   connect(m_d->controller,SIGNAL(axesScaleChanged(int)), this, SLOT(setAxesScale(int)));
@@ -418,7 +432,6 @@ void VP1GeometrySystem::buildPermanentSceneGraph(StoreGateSvc*/*detstore*/, SoSe
       subsys->soswitch->whichChild = SO_SWITCH_ALL;
     //Enable in tree browser:
     m_d->volumetreemodel->enableSubSystem(subsys->flag);
-    //     new ModelTest(m_d->volumetreemodel, m_d->treeView_volumebrowser);
   }
   if (!m_d->restoredTopvolstates.isEmpty()) {
     m_d->applyTopVolStates(m_d->restoredTopvolstates,false);
@@ -498,7 +511,6 @@ GeoPhysVol* VP1GeometrySystem::Imp::createTheWorld(GeoPhysVol* world)
     const GeoMaterial* worldMat = new GeoMaterial("std::Air", densityOfAir);
     const GeoBox* worldBox = new GeoBox(2000*SYSTEM_OF_UNITS::cm, 2000*SYSTEM_OF_UNITS::cm, 2500*SYSTEM_OF_UNITS::cm);
     const GeoLogVol* worldLog = new GeoLogVol("WorldLog", worldBox, worldMat);
-    // GeoPhysVol* worldPhys = new GeoPhysVol(worldLog);
     world = new GeoPhysVol(worldLog);
   }
   return world;
@@ -612,17 +624,16 @@ GeoPhysVol* VP1GeometrySystem::Imp::getGeometryFromLocalDB()
     }
   }
 
-// } // end if m_existingGeoInput
-
   return world;
-
 }
 
+//_____________________________________________________________________________________
 void VP1GeometrySystem::toggleLocalAxes(int i) {
   if (i==0) m_d->axesSwitch->whichChild=SO_SWITCH_NONE;
   else m_d->axesSwitch->whichChild=SO_SWITCH_ALL;
 }
 
+//_____________________________________________________________________________________
 void VP1GeometrySystem::setAxesScale(int i) {
   double x=(i-50)/25.0;
   double scale = pow(10,x);
@@ -657,7 +668,6 @@ void VP1GeometrySystem::checkboxChanged()
     sw->enableNotify(save);
     //Enable in tree browser:
     m_d->volumetreemodel->enableSubSystem(subsys->flag);
-    //     new ModelTest(m_d->volumetreemodel, m_d->treeView_volumebrowser);
     if (save)
       sw->touch();
   } else {
@@ -1031,7 +1041,7 @@ void VP1GeometrySystem::Imp::buildSystem(SubSystemInfo* si)
 	VP1Msg::messageDebug("-- toptree vol: " + QString(it->volname.c_str()) );
 
 	// Get the material name from the top volume and search for it
-	// in the lsit of "default" materials for the sub-detectors:
+	// in the list of "default" materials for the sub-detectors:
 	QString topMaterialName = QString::fromStdString(it->pV->getLogVol()->getMaterial()->getName());
 	VP1Msg::messageDebug("topMaterial: " + topMaterialName);
 	SoMaterial* topMaterial = detVisAttributes->get(it->volname);
@@ -1043,8 +1053,13 @@ void VP1GeometrySystem::Imp::buildSystem(SubSystemInfo* si)
 	}
 
 	VolumeHandleSharedData* volhandle_subsysdata = new VolumeHandleSharedData(controller,
-										  si->flag, &sonodesep2volhandle, it->pV, phisectormanager,
-										  topMaterial, matVisAttributes, volVisAttributes,
+										  si->flag, 
+                                          &sonodesep2volhandle, 
+                                          it->pV, 
+                                          phisectormanager,
+										  topMaterial, 
+                                          matVisAttributes, 
+                                          volVisAttributes,
 										  controller->zappedVolumeListModel(),
 										  controller->volumeTreeBrowser(),
 										  m_textSep);
@@ -1069,7 +1084,6 @@ void VP1GeometrySystem::Imp::buildSystem(SubSystemInfo* si)
 
   //Perform auto expansion of all ether volumes (needed for muon dead material):
   VolumeHandle::VolumeHandleListItr it, itE(si->vollist.end());
-  // int idx=0; // for debug
   for (it = si->vollist.begin(); it!=itE; ++it){
     (*it)->expandMothersRecursivelyToNonEther();
   }
@@ -1282,10 +1296,12 @@ void VP1GeometrySystem::autoExpandByVolumeOrMaterialName(bool bymatname,QString
     return;
   }
 
-  messageVerbose("Auto expansions of visible volumes requested. Target all volumes with "
+    messageVerbose("Auto expansions of **visible** volumes requested. Target all volumes with "
 		 +str(bymatname?"material name":"name")+" matching "+targetname);
 
-  QRegExp selregexp(targetname,Qt::CaseSensitive,QRegExp::Wildcard);
+  //QRegExp selregexp(targetname,Qt::CaseSensitive,QRegExp::Wildcard);
+  QRegExp selregexp(targetname, Qt::CaseSensitive, QRegExp::RegExp);
+  VP1Msg::messageDebug("RegExp pattern: " + selregexp.pattern() );
 
   std::vector<std::pair<VolumeHandle::VolumeHandleListItr,VolumeHandle::VolumeHandleListItr> > roothandles;
   m_d->volumetreemodel->getRootHandles(roothandles);
@@ -1294,49 +1310,95 @@ void VP1GeometrySystem::autoExpandByVolumeOrMaterialName(bool bymatname,QString
   bool save = m_d->sceneroot->enableNotify(false);
   m_d->phisectormanager->largeChangesBegin();
 
-  deselectAll();
+  if (roothandles.size() == 0) {
+    VP1Msg::messageWarningRed("No root nodes selected! Please select at least a root node before trying to apply filters. Ideally, you should turn on only the root node containing the volumes you are interested in; e.g., turn on the 'Endcap MDT' root node, if you are looking for an EIL chamber.");
+  } else {
+    bool save = m_d->sceneroot->enableNotify(false);
+    m_d->phisectormanager->largeChangesBegin();
 
-  for (unsigned i = 0; i<roothandles.size();++i) {
-    it = roothandles.at(i).first;
-    itE = roothandles.at(i).second;
-    for(;it!=itE;++it)
-      m_d->expandVisibleVolumesRecursively(*it,selregexp,bymatname);
-  }
+    deselectAll();
 
-  m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis();
-  m_d->phisectormanager->largeChangesEnd();
-  if (save) {
-    m_d->sceneroot->enableNotify(true);
-    m_d->sceneroot->touch();
+    for (unsigned i = 0; i<roothandles.size();++i) {
+      it = roothandles.at(i).first;
+      itE = roothandles.at(i).second;
+      bool matchFound = false;
+
+      for(;it!=itE;++it) {
+        VolumeHandle* vol = *it;
+        VP1Msg::messageDebug("Looking inside the root node [name: " + vol->getName() + ", material: " + QString::fromStdString(vol->geoMaterial()->getName()) + "]" );
+      	  m_d->expandVisibleVolumesRecursively(vol, selregexp, bymatname);
+      }
+    }
+
+    m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis();
+    m_d->phisectormanager->largeChangesEnd();
+    if (save) {
+      m_d->sceneroot->enableNotify(true);
+      m_d->sceneroot->touch();
+    }
   }
 }
 
 //_____________________________________________________________________________________
 void VP1GeometrySystem::Imp::expandVisibleVolumesRecursively(VolumeHandle* handle,const QRegExp& selregexp,bool bymatname)
 {
-  if (handle->state()==VP1GeoFlags::ZAPPED)
+  //if (handle->state()==VP1GeoFlags::ZAPPED)
+  //  return;
+  VP1Msg::messageDebug("VP1GeometrySystem::Imp::expandVisibleVolumesRecursively()");
+  if (handle->state()==VP1GeoFlags::ZAPPED) {
+	VP1Msg::messageDebug(handle->getName() +" is ZAPPED. Returning...");
     return;
+  }
+
   if (handle->state()==VP1GeoFlags::CONTRACTED) {
+    VP1Msg::messageDebug(handle->getName() +" is CONTRACTED. Going on...");
     //See if we match (and have children) - if so, update state.
     if (handle->nChildren()>0
-	&& selregexp.exactMatch(bymatname?QString(handle->geoMaterial()->getName().c_str()):handle->getName())) {
+	&& selregexp.exactMatch(bymatname?QString(handle->geoMaterial()->getName().c_str()):handle->getName())) 
+    {
+      VP1Msg::messageDebug(handle->getName() +" has >0 children: OK! Setting it to 'EXPANDED'.");
       handle->setState(VP1GeoFlags::EXPANDED);
     }
+    VP1Msg::messageDebug(handle->getName() +" - Now returning...");
     return;
   }
+  
   //Must be expanded: Let us call on any (initialised) children instead.
-  if (handle->nChildren()==0||!handle->childrenAreInitialised())
+  if (handle->nChildren()==0||!handle->childrenAreInitialised()) {
+    VP1Msg::messageDebug(handle->getName() +" has NO children or they are not initialized. Returning...");
     return;
+  }
+
+  //TODO: does the code comes here ever??? Check!
+  VP1Msg::messageDebug(handle->getName() +" - Now looping over children...");
   VolumeHandle::VolumeHandleListItr it(handle->childrenBegin()), itE(handle->childrenEnd());
-  for(;it!=itE;++it)
+  for(;it!=itE;++it) {
     expandVisibleVolumesRecursively(*it,selregexp,bymatname);
+  }
 }
 
 
+//_____________________________________________________________________________________
+void VP1GeometrySystem::volumeStateChangeRequested(VolumeHandle*vh,VP1GeoFlags::VOLSTATE state)
+{
+  //might not use this slot presently...
+  if (!vh)
+    return;
+  deselectAll();
+  vh->setState(state);
+  m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis();
+}
 
 
-
-
+//_____________________________________________________________________________________
+void VP1GeometrySystem::volumeResetRequested(VolumeHandle*vh)
+{
+  if (!vh)
+    return;
+  deselectAll();
+  vh->reset();
+  m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis();
+}
 
 
 //_____________________________________________________________________________________
@@ -1447,7 +1509,7 @@ void VP1GeometrySystem::loadMaterialsFromFile(QString filename)
 
 
 
-
+//_____________________________________________________________________________________
 void VP1GeometrySystem::saveTrees() {
 #ifdef __APPLE__
   char buffer[1024];
@@ -1496,6 +1558,7 @@ void VP1GeometrySystem::saveTrees() {
   world->unref();
 }
 
+//_____________________________________________________________________________________
 GeoPhysVol *VP1GeometrySystem::newWorld()  const {
   const double  gr =   SYSTEM_OF_UNITS::gram;
   const double  mole = SYSTEM_OF_UNITS::mole;
@@ -1520,3 +1583,277 @@ GeoPhysVol *VP1GeometrySystem::newWorld()  const {
   GeoPhysVol* world = new GeoPhysVol(worldLog);
   return world;
 }
+
+
+//_____________________________________________________________________________________
+void VP1GeometrySystem::filterVolumes(QString targetname, bool bymatname, int maxDepth = 1, bool stopAtFirst = true, bool visitChildren = false, bool resetView = false)
+{
+
+  // initialize the regular expression
+  QRegExp selregexp(targetname, Qt::CaseSensitive, QRegExp::RegExp);
+  // VP1Msg::messageDebug("RegExp pattern: " + selregexp.pattern()  );
+  
+  QStringList ll;
+  ll << "VP1GeometrySystem::filterVolumes" << "RegExp pattern:" << selregexp.pattern() 
+     << "- maxDepth:" << QString::number(maxDepth)
+     << "- stopAtFirst:" << QString::number(stopAtFirst) 
+     << "- visitChildren:" << QString::number(visitChildren) 
+     << "- resetView:" << QString::number(resetView);
+  VP1Msg::messageDebug(ll.join(" "));
+
+   
+   // get root handles list
+  std::vector<std::pair<VolumeHandle::VolumeHandleListItr,VolumeHandle::VolumeHandleListItr> > roothandles;
+  m_d->volumetreemodel->getRootHandles(roothandles);
+  VolumeHandle::VolumeHandleListItr it, itE;
+  
+  bool save = m_d->sceneroot->enableNotify(false);
+  m_d->phisectormanager->largeChangesBegin();
+  deselectAll();
+
+  bool zapAll = false; // TODO: do we need that?
+  bool matchFound = false;
+  unsigned nFound = 0;
+  
+  // loop over root handles
+  for (unsigned i = 0; i<roothandles.size();++i) {
+    it = roothandles.at(i).first;
+    itE = roothandles.at(i).second;
+
+    // loop over root volumes
+    for(;it!=itE;++it) {
+
+        VolumeHandle* handle = (*it);
+
+        VP1Msg::messageDebug("Looking at the root node [name: " + handle->getName() + ", mat: " + QString::fromStdString(handle->geoMaterial()->getName()) + "]" );
+        m_d->filterVolumesRec(handle, selregexp, bymatname, stopAtFirst, visitChildren, resetView, zapAll, matchFound, nFound, maxDepth);
+        VP1Msg::messageDebug("matchFound: " + QString::number(matchFound));
+        
+        if (resetView) {
+            VP1Msg::messageDebug("'expanding' and 'contracting' the root volume...");
+            // in the call to 'filterVolumesRec' above, when resetting the view, 
+            // we have 'contracted' the root volume and all the children we had 'zapped' before.
+            // So, now we need to open ('expand'), and then close ('contract') the root volume again,
+            // in order to get rid of the manually-contracted volumes.
+            handle->setState(VP1GeoFlags::EXPANDED); 
+            handle->setState(VP1GeoFlags::CONTRACTED); 
+        }
+
+    } // end loop over root volumes
+  } // loop over root handles
+
+  // give feedback to the user
+  message("[filter volumes] # of matching volumes: " + QString::number(nFound));
+  
+  //if user chose to visit children of matching volumes,
+  //then we change transparency type to 'Sorted Object Blend', usually better to visualize nested volumes
+  if (visitChildren && (nFound>0) ) {
+      message(  QString("[filter volumes] NOTE: to show both matching mother and matching daughter volumes, ") 
+              + QString("transparency has been set to 50% and transparency type has been changed to 'Sorted Object Blend', ")
+              + QString("which is usually better to visualize nested geometry volumes. ")
+              + QString("You can disable this auto-setting by checking the 'lock'.") );
+      if ( ! m_d->controller->isTranspLocked()) {
+          m_d->controller->setTransparency(50);
+          emit updateTransparencyType( VP1QtInventorUtils::transparencyTypeToInt(SoGLRenderAction::SORTED_OBJECT_BLEND) );
+      }
+  }
+
+
+  VP1Msg::messageDebug("largeChangesEnding...");
+  m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis();
+  m_d->phisectormanager->largeChangesEnd();
+  if (save) {
+    m_d->sceneroot->enableNotify(true);
+    m_d->sceneroot->touch();
+  }
+
+}
+//_____________________________________________________________________________________
+bool VP1GeometrySystem::Imp::filterVolumesRec(VolumeHandle* handle, QRegExp selregexp, bool bymatname, bool stopAtFirst, bool visitChildren, bool resetView, bool &zapAll, bool &matchFound, unsigned &nFound, int maxIter, unsigned int iter)
+{
+      if (!zapAll) {
+        VP1Msg::messageDebug2("iteration: " + QString::number(iter) + ", maxIter: " + QString::number(maxIter));
+        VP1Msg::messageDebug2("looking into volume: " + handle->getName());
+      }
+      
+      // zap the current volume by default...
+      handle->setState(VP1GeoFlags::ZAPPED);
+
+      VP1Msg::messageDebug2("filtering: " + handle->getName() );
+
+      if ( !zapAll ) {
+        if ( !resetView ) {
+          //... then unzap the volume if it matches the filter regex
+          if (selregexp.exactMatch( bymatname ? QString(handle->geoMaterial()->getName().c_str()) : handle->getName()) ) 
+          {
+            matchFound = true;
+            ++nFound;
+            VP1Msg::messageDebug(handle->getName() +" - **MATCH!** - 'Contracting' it (-->make it visible)...");
+            handle->setState(VP1GeoFlags::CONTRACTED); // match, make the matching volume visible
+            // if a matching volume was found and 'stop at first' option was choosen, then stop here
+            //VP1Msg::messageDebug2("matchFound: " + QString::number(matchFound) + " - stopAtFirst: " + QString::number(stopAtFirst));
+            
+            if (stopAtFirst && matchFound) {
+              VP1Msg::messageDebug("\tYou chose to show only the first matching volume, so we stop here - exiting from the inner children loop...");
+              //return matchFound;
+              zapAll = true;
+            } 
+          } else {
+            VP1Msg::messageDebug2("not matching --> zapping it");
+            handle->setState(VP1GeoFlags::ZAPPED); // no match, open the volume to show its children
+          }
+        }
+        if (resetView) {
+          if(handle->state()!=VP1GeoFlags::CONTRACTED) {
+              VP1Msg::messageDebug2("resetView --> contracting it");
+              handle->setState(VP1GeoFlags::CONTRACTED); // open the volume to show its children
+          }
+        }
+      } // end if !zapAll
+
+
+      // check iterations, a.k.a., the 'maxDepth', i.e., the number of layers of daughter volumes visited 
+      if( maxIter != -1 && iter == maxIter) {
+          VP1Msg::messageDebug("maxIter [" + QString::number(iter) + "] reached, returning from the recursive method and go to the next upper volume...");
+          return matchFound;
+      }
+       // increment the iteration number
+      iter++;
+      
+      // if no match yet, 
+      // or if user asked to visit children of matching volumes too, 
+      // then loop over children
+      if ( !matchFound || (matchFound && visitChildren) ) {
+          if (!zapAll) {
+              VP1Msg::messageDebug2("No match, or you chose to inspect all child volumes, so we look into the children...");
+          }
+          if (handle->nChildren()>0) {
+              // get children list
+              handle->initialiseChildren();
+              VolumeHandle::VolumeHandleListItr itChl(handle->childrenBegin()),itChlE(handle->childrenEnd());
+              for (;itChl!=itChlE;++itChl) {
+
+                  VolumeHandle* child = (*itChl);
+
+                  // filter children volumes recursively
+                  filterVolumesRec(child, selregexp, bymatname, stopAtFirst, visitChildren, resetView, zapAll, matchFound, nFound, maxIter, iter);
+                  if (stopAtFirst && matchFound) {
+                      //return matchFound;
+                      zapAll = true;
+                  }
+              } // end loop over children
+          
+              if (resetView) {
+                 // in the call to 'filterVolumesRec' above, when resetting the view, 
+                 // we have 'contracted' the root volume and all the children we had 'zapped' before.
+                 // So, now we need to open ('expand'), and then close ('contract') the root volume again,
+                 // in order to get rid of the manually-contracted volumes.
+                 handle->setState(VP1GeoFlags::EXPANDED); 
+                 handle->setState(VP1GeoFlags::CONTRACTED); 
+              }
+          }
+      }
+
+      return matchFound;
+}
+
+
+
+
+
+
+
+
+
+
+
+// =========================
+
+////////
+// Methods which come from VP1 and have been rplaced by other methods, 
+// but they are useful for later use,
+// when we try to act on all volumes
+////////
+
+// Not used at the moment, but useful
+//_____________________________________________________________________________________
+void VP1GeometrySystem::Imp::changeStateOfAllVolumesRecursively(VolumeHandle*handle,VP1GeoFlags::VOLSTATE target)
+{
+    handle->initialiseChildren();
+    handle->setState(target);
+    VolumeHandle::VolumeHandleListItr itChl(handle->childrenBegin()),itChlE(handle->childrenEnd());
+
+    // loop over second level children 
+    for (;itChl!=itChlE;++itChl) {
+        changeStateOfAllVolumesRecursively(*itChl, target);
+    }
+}
+
+
+// Not used at the moment, but useful
+//_____________________________________________________________________________________
+void VP1GeometrySystem::Imp::changeStateOfVisibleNonStandardVolumesRecursively(VolumeHandle*handle,VP1GeoFlags::VOLSTATE target)
+{
+  assert(target!=VP1GeoFlags::CONTRACTED);
+  if (handle->isAttached()) {
+    //The volume is visible, so ignore daughters
+    if (handle->isInitialisedAndHasNonStandardShape()) {
+      if (target!=VP1GeoFlags::EXPANDED||handle->nChildren()>0)
+	handle->setState(target);
+    }
+    return;
+  } else if (handle->state()==VP1GeoFlags::ZAPPED)
+    return;
+  //Must be expanded: Let us call on any (initialised) children instead.
+  if (handle->nChildren()==0||!handle->childrenAreInitialised())
+    return;
+  VolumeHandle::VolumeHandleListItr it(handle->childrenBegin()), itE(handle->childrenEnd());
+  for(;it!=itE;++it)
+    changeStateOfVisibleNonStandardVolumesRecursively(*it, target);
+}
+
+// Not used at the moment, but useful
+//_____________________________________________________________________________________
+void VP1GeometrySystem::actionOnAllNonStandardVolumes(bool zap)
+{
+  actionOnAllVolumes(zap, false);
+}
+
+// Not used at the moment, but useful
+//_____________________________________________________________________________________
+void VP1GeometrySystem::actionOnAllVolumes(bool zap, bool standardVolumes /* default: true*/)
+{
+  //VP1GeoFlags::VOLSTATE target = zap ? VP1GeoFlags::ZAPPED : VP1GeoFlags::EXPANDED;
+  VP1GeoFlags::VOLSTATE target = zap ? VP1GeoFlags::ZAPPED : VP1GeoFlags::CONTRACTED;
+  messageVerbose("Action on volumes with non-standard VRML representations. Target state is "+VP1GeoFlags::toString(target));
+
+  std::vector<std::pair<VolumeHandle::VolumeHandleListItr,VolumeHandle::VolumeHandleListItr> > roothandles;
+  m_d->volumetreemodel->getRootHandles(roothandles);
+  VolumeHandle::VolumeHandleListItr it, itE;
+
+  bool save = m_d->sceneroot->enableNotify(false);
+  m_d->phisectormanager->largeChangesBegin();
+
+  deselectAll();
+
+  for (unsigned i = 0; i<roothandles.size();++i) {
+    it = roothandles.at(i).first;
+    itE = roothandles.at(i).second;
+    for(;it!=itE;++it) {
+      if (standardVolumes) {
+        m_d->changeStateOfAllVolumesRecursively(*it, target);
+      } else {
+        m_d->changeStateOfVisibleNonStandardVolumesRecursively(*it, target);
+      }
+    }
+  }
+
+  m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis();
+  m_d->phisectormanager->largeChangesEnd();
+  if (save) {
+    m_d->sceneroot->enableNotify(true);
+    m_d->sceneroot->touch();
+  }
+}
+
+
diff --git a/GeoModelVisualization/VP1GeometrySystems/src/VolumeHandle.cxx b/GeoModelVisualization/VP1GeometrySystems/src/VolumeHandle.cxx
index e6001ea5d937288589267b490481b0f57a0c9e41..d40b20423f1811b54863f60bdcc89b6f6a995183 100644
--- a/GeoModelVisualization/VP1GeometrySystems/src/VolumeHandle.cxx
+++ b/GeoModelVisualization/VP1GeometrySystems/src/VolumeHandle.cxx
@@ -73,6 +73,7 @@ public:
 
   static VolState getChildStates(const VolumeHandle*theclass );
   static void applyChildStates(const VolState&,VolumeHandle*theclass);
+  static bool hasNonStandardShapeChildren(const SoGroup*g);
 
 };
 
@@ -181,7 +182,7 @@ bool VolumeHandle::hasName(const std::string& n) const
 //____________________________________________________________________
 SoMaterial * VolumeHandle::material()
 {
-  VP1Msg::messageDebug("VolumeHandle::material() - LogVol name: " + QString::fromStdString(m_d->pV->getLogVol()->getName()));
+  VP1Msg::messageDebug2("VolumeHandle::material() - LogVol name: " + QString::fromStdString(m_d->pV->getLogVol()->getName()));
   // if it's not the first time here and
   // the material has been assigned already, then return that
   if (m_d->material)
@@ -238,7 +239,7 @@ SoSeparator * VolumeHandle::nodeSoSeparator() const
 //____________________________________________________________________
 void VolumeHandle::ensureBuildNodeSep()
 {
-  VP1Msg::messageDebug("VolumeHandle::ensureBuildNodeSep()");
+  VP1Msg::messageDebug3("VolumeHandle::ensureBuildNodeSep()");
   if (m_d->nodesep && m_d->label_sep)
     return;
 
@@ -344,15 +345,15 @@ void VolumeHandle::ensureBuildNodeSep()
 //____________________________________________________________________
 void VolumeHandle::Imp::attach(VolumeHandle*vh)
 {
-  VP1Msg::messageDebug("VolumeHandle::Imp::attach() - name: " + vh->getName());
+  VP1Msg::messageDebug3("VolumeHandle::Imp::attach() - name: " + vh->getName());
   if (!isattached) {
     vh->ensureBuildNodeSep();
     if (attachsepHelper) {
-      VP1Msg::messageDebug("adding node...");
+      VP1Msg::messageDebug3("adding node...");
       attachsepHelper->addNodeUnderMaterial(nodesep,vh->material());
     }
     if (attachlabelSepHelper) {
-      VP1Msg::messageDebug("adding label...");
+      VP1Msg::messageDebug3("adding label...");
       attachlabelSepHelper->addNode(label_sep);
     }
     isattached=true;
@@ -682,6 +683,35 @@ void VolumeHandle::Imp::applyChildStates(const VolState& vs,VolumeHandle*theclas
 }
 
 
+//____________________________________________________________________
+bool VolumeHandle::Imp::hasNonStandardShapeChildren(const SoGroup*g)
+{
+  const int n(g->getNumChildren());
+  for (int i=0; i < n; ++i) {
+    const SoNode*c = g->getChild(i);
+    if (c->getTypeId().isDerivedFrom(SoShape::getClassTypeId())) {
+      if (c->getTypeId().isDerivedFrom(SoPcons::getClassTypeId())
+	  ||c->getTypeId().isDerivedFrom(SoPolyhedron::getClassTypeId())
+	  ||c->getTypeId().isDerivedFrom(SoTransparency::getClassTypeId()))
+	return true;
+    } else if (c->getTypeId().isDerivedFrom(SoGroup::getClassTypeId())) {
+      if (hasNonStandardShapeChildren(static_cast<const SoGroup*>(c)))
+	return true;
+    }
+  }
+  return false;
+}
+
+//____________________________________________________________________
+bool VolumeHandle::isInitialisedAndHasNonStandardShape() const
+{
+  VP1HEPVisUtils::initAllCustomClasses();
+  return m_d->nodesep ? Imp::hasNonStandardShapeChildren(m_d->nodesep) : false;
+}
+
+
+
+
 //____________________________________________________________________
 bool VolumeHandle::isPositiveZ() const
 {
diff --git a/GeoModelVisualization/VP1GeometrySystems/src/VolumeTreeModel.cxx b/GeoModelVisualization/VP1GeometrySystems/src/VolumeTreeModel.cxx
index addc936508f3f5a20074b70bb6bb534d5f6476d8..64a6f3e10b36e0241eae099518b6b388ddff6454 100644
--- a/GeoModelVisualization/VP1GeometrySystems/src/VolumeTreeModel.cxx
+++ b/GeoModelVisualization/VP1GeometrySystems/src/VolumeTreeModel.cxx
@@ -337,11 +337,17 @@ QVariant VolumeTreeModel::data(const QModelIndex& index, int role) const
       else
 	return QColor::fromRgbF( 0.5, 0.5, 0.5 );
     }
+    
     //DisplayRole:
-    if (volumeHandle->nChildren()>1)
-      return volumeHandle->getName() + " (" + QString::fromStdString(volumeHandle->geoMaterial()->getName()) + ") [" + QString::number(volumeHandle->nChildren())+"]";
+    
+    QString volState = "e";
+    if(volumeHandle->state()==VP1GeoFlags::CONTRACTED) volState = "c";
+    else if(volumeHandle->state()==VP1GeoFlags::ZAPPED) volState = "z";
+
+    if (volumeHandle->nChildren()>0)
+      return volumeHandle->getName() + " (" + QString::fromStdString(volumeHandle->geoMaterial()->getName()) + ") [" + QString::number(volumeHandle->nChildren())+"] ("+ volState + ")" ;
     else
-      return volumeHandle->getName() + " (" + QString::fromStdString(volumeHandle->geoMaterial()->getName()) + ")";
+      return volumeHandle->getName() + " (" + QString::fromStdString(volumeHandle->geoMaterial()->getName()) + ") ("+ volState + ")" ;
   }
 
   if (role==Qt::TextColorRole)
diff --git a/GeoModelVisualization/VP1GeometrySystems/src/settings_misc_form.ui b/GeoModelVisualization/VP1GeometrySystems/src/settings_misc_form.ui
index da0b4cd0d52287e59120c693ebfc03a5030ac8cd..76bb969dc337fd788dbfdfa09a33c062227e9b85 100644
--- a/GeoModelVisualization/VP1GeometrySystems/src/settings_misc_form.ui
+++ b/GeoModelVisualization/VP1GeometrySystems/src/settings_misc_form.ui
@@ -6,20 +6,50 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>370</width>
-    <height>425</height>
+    <width>387</width>
+    <height>701</height>
    </rect>
   </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Ignored">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="minimumSize">
+   <size>
+    <width>0</width>
+    <height>701</height>
+   </size>
+  </property>
+  <property name="maximumSize">
+   <size>
+    <width>387</width>
+    <height>701</height>
+   </size>
+  </property>
   <property name="windowTitle">
-   <string>Form</string>
+   <string>Mis. settings</string>
   </property>
-  <layout class="QVBoxLayout" name="verticalLayout_2">
-   <item>
-    <widget class="QGroupBox" name="groupBox">
+  <layout class="QGridLayout" name="gridLayout">
+   <property name="sizeConstraint">
+    <enum>QLayout::SetMinimumSize</enum>
+   </property>
+   <item row="0" column="0">
+    <widget class="QGroupBox" name="actionsGroupBox">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="MinimumExpanding" vsizetype="Maximum">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
      <property name="title">
       <string>Actions on visible volumes</string>
      </property>
      <layout class="QGridLayout" name="_5">
+      <property name="sizeConstraint">
+       <enum>QLayout::SetMinimumSize</enum>
+      </property>
       <property name="leftMargin">
        <number>4</number>
       </property>
@@ -98,29 +128,260 @@ p, li { white-space: pre-wrap; }
      </layout>
     </widget>
    </item>
-   <item>
-    <layout class="QHBoxLayout" name="_10">
-     <item>
-      <spacer>
-       <property name="orientation">
-        <enum>Qt::Horizontal</enum>
-       </property>
-       <property name="sizeHint" stdset="0">
-        <size>
-         <width>40</width>
-         <height>20</height>
-        </size>
-       </property>
-      </spacer>
-     </item>
-     <item>
-      <widget class="QPushButton" name="pushButton_close">
-       <property name="text">
-        <string>&amp;Close</string>
-       </property>
-      </widget>
-     </item>
-    </layout>
+   <item row="1" column="0">
+    <widget class="QGroupBox" name="filtersGroupBox">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="title">
+      <string>Filter volumes</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout_4">
+      <property name="sizeConstraint">
+       <enum>QLayout::SetMinimumSize</enum>
+      </property>
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout_6">
+        <item>
+         <widget class="QLabel" name="label_filter_logVolName">
+          <property name="text">
+           <string>LogVol's name:</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLineEdit" name="lineEdit_filter_logvolname">
+          <property name="toolTip">
+           <string>Filter geometry volumes based on the name of the GeoLogVol node. You can use regular expressions and wildcards (*).</string>
+          </property>
+          <property name="placeholderText">
+           <string>ex: Inner.*     [regexp]</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QPushButton" name="pushButton_filter_logvolname">
+          <property name="text">
+           <string>Apply</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout">
+        <item>
+         <widget class="QLabel" name="label_maxDepth">
+          <property name="toolTip">
+           <string>The maximum number of daughter volumes visited. Note: default is '1';  '0' means 'only root/top volumes';  '-1' means 'MAX', but can be VERY slow depending on the geometry complexity.</string>
+          </property>
+          <property name="statusTip">
+           <string>The maximum number of daughter volumes visited. Note: default is '1';  '0' means 'only root/top volumes';  '-1' means 'MAX', but can be VERY slow depending on the geometry complexity.</string>
+          </property>
+          <property name="whatsThis">
+           <string>The maximum number of daughter volumes visited. Note: default is '1';  '0' means 'only root/top volumes';  '-1' means 'MAX', but can be VERY slow depending on the geometry complexity.</string>
+          </property>
+          <property name="text">
+           <string>max. depth</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QSpinBox" name="spinBox_maxDepth">
+          <property name="toolTip">
+           <string>The maximum number of daughter volumes visited. Note: default is '1';  '0' means 'only root/top volumes';  '-1' means 'MAX', but can be VERY slow depending on the geometry complexity.</string>
+          </property>
+          <property name="statusTip">
+           <string>The maximum number of daughter volumes visited. Note: default is '1';  '0' means 'only root/top volumes';  '-1' means 'MAX', but can be VERY slow depending on the geometry complexity.</string>
+          </property>
+          <property name="whatsThis">
+           <string>The maximum number of daughter volumes visited. Note: default is '1';  '0' means 'only root/top volumes';  '-1' means 'MAX', but can be VERY slow depending on the geometry complexity.</string>
+          </property>
+          <property name="minimum">
+           <number>-1</number>
+          </property>
+          <property name="maximum">
+           <number>99</number>
+          </property>
+          <property name="value">
+           <number>1</number>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="label_2">
+          <property name="text">
+           <string>[0: top volumes; -1: All (slower)]</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer name="horizontalSpacer">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>40</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <widget class="QGroupBox" name="groupBox_3">
+        <property name="title">
+         <string>How many matching volumes should I show?</string>
+        </property>
+        <layout class="QHBoxLayout" name="horizontalLayout_10">
+         <item>
+          <widget class="QRadioButton" name="radioButton_StopAtFirst">
+           <property name="toolTip">
+            <string>Default. Stop after a first match has been found. Useful for a quick check.</string>
+           </property>
+           <property name="text">
+            <string>Show the first match</string>
+           </property>
+           <property name="checked">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QRadioButton" name="radioButton_LoopOverAll">
+           <property name="toolTip">
+            <string>Look for all volumes matching the filter string. ATTENTION, it can take a lof of time.</string>
+           </property>
+           <property name="text">
+            <string>Show all (slower)</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
+      <item>
+       <widget class="QGroupBox" name="groupBox_4">
+        <property name="title">
+         <string>Do you want to visit children of matching volumes?</string>
+        </property>
+        <layout class="QGridLayout" name="gridLayout_2">
+         <item row="0" column="1">
+          <widget class="QRadioButton" name="radioButton_VisitAllChildren">
+           <property name="toolTip">
+            <string>When a volume matches the filter, do visit all its child volumes as well. It can be slow.</string>
+           </property>
+           <property name="statusTip">
+            <string>When a volume matches the filter, do visit all its child volumes as well. It can be slow.</string>
+           </property>
+           <property name="whatsThis">
+            <string>When a volume matches the filter, do visit all its child volumes as well. It can be slow.</string>
+           </property>
+           <property name="accessibleDescription">
+            <string>When a volume matches the filter, do visit all its child volumes as well. It can be slow.</string>
+           </property>
+           <property name="text">
+            <string>Visit All Children</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="0">
+          <widget class="QRadioButton" name="radioButton_DoNotVisitChildren">
+           <property name="toolTip">
+            <string>Default. When a volume matches the filter, do not visit its child volumes.</string>
+           </property>
+           <property name="text">
+            <string>Do Not Visit Children</string>
+           </property>
+           <property name="checked">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="1">
+          <widget class="QCheckBox" name="lockTransp">
+           <property name="toolTip">
+            <string>When enabling 'Visit All Children', if there are matching daughter to be shown inside a matching mother volume, then the transparency will be automatically set to 50% and set to a given type, to ease the visualization of nested volumes. You can disable this by checking this.</string>
+           </property>
+           <property name="statusTip">
+            <string>When enabling 'Visit All Children', if there are matching daughter to be shown inside a matching mother volume, then the transparency will be automatically set to 50% and set to a given type, to ease the visualization of nested volumes. You can disable this by checking this.</string>
+           </property>
+           <property name="whatsThis">
+            <string>When enabling 'Visit All Children', if there are matching daughter to be shown inside a matching mother volume, then the transparency will be automatically set to 50% and set to a given type, to ease the visualization of nested volumes. You can disable this by checking this.</string>
+           </property>
+           <property name="accessibleDescription">
+            <string>When enabling 'Visit All Children', if there are matching daughter to be shown inside a matching mother volume, then the transparency will be automatically set to 50% and set to a given type. You can disable this by checking this.</string>
+           </property>
+           <property name="text">
+            <string>[lock transparency]</string>
+           </property>
+          </widget>
+         </item>
+         <item row="1" column="1">
+          <widget class="QLabel" name="label">
+           <property name="text">
+            <string>(slower)</string>
+           </property>
+           <property name="alignment">
+            <set>Qt::AlignCenter</set>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
+      <item>
+       <widget class="QPushButton" name="pushButton_filter_reset">
+        <property name="toolTip">
+         <string>Visualize all volumes by removing all filters.</string>
+        </property>
+        <property name="text">
+         <string>Reset filters</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="2" column="0">
+    <widget class="QGroupBox" name="groupBox">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <layout class="QHBoxLayout" name="bottomLayout">
+      <property name="sizeConstraint">
+       <enum>QLayout::SetMinimumSize</enum>
+      </property>
+      <item>
+       <spacer name="horizontalSpacer_2">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>40</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QPushButton" name="pushButton_close">
+        <property name="text">
+         <string>&amp;Close</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
    </item>
   </layout>
  </widget>