Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-12-02 10:36:07

0001 // -*- C++ -*-
0002 //
0003 // Package:     Core
0004 // Class  :     FWEveViewManager
0005 //
0006 // Implementation:
0007 //     [Notes on implementation]
0008 //
0009 // Original Author:  Chris Jones, Alja Mrak-Tadel
0010 //         Created:  Thu Mar 18 14:11:32 CET 2010
0011 //
0012 
0013 // system include files
0014 
0015 #include <functional>
0016 
0017 // user include files
0018 #include "TEveManager.h"
0019 #include "TEveSelection.h"
0020 #include "TEveScene.h"
0021 #include "TEveViewer.h"
0022 #include "TEveCalo.h"
0023 #include "TEveGedEditor.h"
0024 #include "TGListTree.h"
0025 #include "TGeoManager.h"
0026 #include "TExMap.h"
0027 #include "TEnv.h"
0028 
0029 #include "Fireworks/Core/interface/FWEveViewManager.h"
0030 #include "Fireworks/Core/interface/FWSelectionManager.h"
0031 #include "Fireworks/Core/interface/FWColorManager.h"
0032 #include "Fireworks/Core/interface/Context.h"
0033 #include "Fireworks/Core/interface/FWInteractionList.h"
0034 #include "Fireworks/Core/interface/CmsShowCommon.h"
0035 #include "Fireworks/Core/interface/fwLog.h"
0036 #include "Fireworks/Core/interface/FWViewEnergyScale.h"
0037 #include "Fireworks/Core/interface/FWSimpleRepresentationChecker.h"
0038 
0039 // PB
0040 #include "Fireworks/Core/interface/FWEDProductRepresentationChecker.h"
0041 #include "Fireworks/Core/interface/FWSimpleRepresentationChecker.h"
0042 #include "Fireworks/Core/interface/FWTypeToRepresentations.h"
0043 #include "Fireworks/Core/interface/FWEventItem.h"
0044 #include "Fireworks/Core/interface/FWProxyBuilderFactory.h"
0045 #include "Fireworks/Core/interface/FWProxyBuilderBase.h"
0046 
0047 // viewes
0048 #include "Fireworks/Core/interface/FWGUIManager.h"
0049 #include "Fireworks/Core/interface/FWISpyView.h"
0050 #include "Fireworks/Core/interface/FW3DView.h"
0051 #include "Fireworks/Core/interface/FWGlimpseView.h"
0052 #include "Fireworks/Core/interface/FWEveLegoView.h"
0053 #include "Fireworks/Core/interface/FWHFView.h"
0054 #include "Fireworks/Core/interface/FWRPZView.h"
0055 
0056 #include "Fireworks/Core/interface/FWTGLViewer.h"
0057 bool FWEveViewManager::s_syncAllViews = false;
0058 
0059 class FWViewContext;
0060 
0061 // sentry class block TEveSelection signals when call TEveSelection::Remove/AddElement and
0062 // when process its callbacks
0063 class EveSelectionSentry {
0064 public:
0065   EveSelectionSentry() { m_blocked = gEve->GetSelection()->BlockSignals(true); }
0066   ~EveSelectionSentry() { gEve->GetSelection()->BlockSignals(m_blocked); }
0067 
0068 private:
0069   bool m_blocked;
0070 };
0071 
0072 //
0073 //
0074 // constants, enums and typedefs
0075 //
0076 //
0077 // constructors and destructor
0078 //
0079 FWEveViewManager::FWEveViewManager(FWGUIManager* iGUIMgr) : FWViewManagerBase() {
0080   // builders
0081   std::set<std::string> builders;
0082 
0083   std::vector<edmplugin::PluginInfo> available = FWProxyBuilderFactory::get()->available();
0084   std::transform(available.begin(),
0085                  available.end(),
0086                  std::inserter(builders, builders.begin()),
0087                  std::bind(&edmplugin::PluginInfo::name_, std::placeholders::_1));
0088 
0089   if (edmplugin::PluginManager::get()->categoryToInfos().end() !=
0090       edmplugin::PluginManager::get()->categoryToInfos().find(FWProxyBuilderFactory::get()->category())) {
0091     available =
0092         edmplugin::PluginManager::get()->categoryToInfos().find(FWProxyBuilderFactory::get()->category())->second;
0093     std::transform(available.begin(),
0094                    available.end(),
0095                    std::inserter(builders, builders.begin()),
0096                    std::bind(&edmplugin::PluginInfo::name_, std::placeholders::_1));
0097   }
0098 
0099   for (std::set<std::string>::iterator it = builders.begin(), itEnd = builders.end(); it != itEnd; ++it) {
0100     std::string::size_type first = it->find_first_of('@') + 1;
0101     std::string purpose = it->substr(first, it->find_last_of('@') - first);
0102 
0103     first = it->find_last_of('@') + 1;
0104     std::string view_str = it->substr(first, it->find_last_of('#') - first);
0105     int viewTypes = atoi(view_str.c_str());
0106     m_typeToBuilder[purpose].push_back(BuilderInfo(*it, viewTypes));
0107   }
0108 
0109   m_views.resize(FWViewType::kTypeSize);
0110 
0111   // view construction called via GUI mng
0112   FWGUIManager::ViewBuildFunctor f =
0113       std::bind(&FWEveViewManager::buildView, this, std::placeholders::_1, std::placeholders::_2);
0114   for (int i = 0; i < FWViewType::kTypeSize; i++) {
0115     if (i == FWViewType::kTable || i == FWViewType::kTableHLT || i == FWViewType::kTableL1)
0116       continue;
0117     iGUIMgr->registerViewBuilder(FWViewType::idToName(i), f);
0118   }
0119 
0120   // signal
0121   gEve->GetHighlight()->SetPickToSelect(TEveSelection::kPS_Master);
0122   TEveSelection* eveSelection = gEve->GetSelection();
0123   eveSelection->SetPickToSelect(TEveSelection::kPS_Master);
0124   eveSelection->Connect("SelectionAdded(TEveElement*)", "FWEveViewManager", this, "selectionAdded(TEveElement*)");
0125   eveSelection->Connect("SelectionRepeated(TEveElement*)", "FWEveViewManager", this, "selectionAdded(TEveElement*)");
0126   eveSelection->Connect("SelectionRemoved(TEveElement*)", "FWEveViewManager", this, "selectionRemoved(TEveElement*)");
0127   eveSelection->Connect("SelectionCleared()", "FWEveViewManager", this, "selectionCleared()");
0128 
0129   gEve->GetHighlight()->Connect(
0130       "SelectionAdded(TEveElement*)", "FWEveViewManager", this, "highlightAdded(TEveElement*)");
0131   gEve->GetHighlight()->Connect(
0132       "SelectionRepeated(TEveElement*)", "FWEveViewManager", this, "highlightAdded(TEveElement*)");
0133 
0134   TGeoManager::SetVerboseLevel(0);
0135 }
0136 
0137 FWEveViewManager::~FWEveViewManager() {}
0138 
0139 //
0140 // member functions
0141 //
0142 
0143 //______________________________________________________________________________
0144 
0145 /**
0146    Helper function to add products from a given builder to a given view.
0147    FWRPZView is a base class for all projected views 
0148     (name derives from  FWViewType::RPhi and FWViewType::RhoZ projection).
0149   */
0150 void addElements(const FWEventItem* item, FWEveView* view, int viewType, TEveElementList* product) {
0151   if (FWViewType::isProjected(viewType)) {
0152     FWRPZView* rpzView = dynamic_cast<FWRPZView*>(view);
0153     assert(rpzView);
0154     rpzView->importElements(product, item->layer(), rpzView->eventScene());
0155   } else {
0156     view->eventScene()->AddElement(product);
0157   }
0158 }
0159 
0160 /** This  is  invoked  when  a  new  item  is  created
0161     by  the  FWEventItemsManager.  The  workflow  is  the  following
0162 
0163    1.  First  we  check  if  we  have  a  builder  info  for  the  given  purpose  of  the
0164        item.  We  return  simply  if  we  don't.
0165    2.  We  iterate  over  all  the  proxy  builder  registered  for  the  given
0166        purpose  and  create  a  new  one  for  this  given  item.
0167    3.  Interaction  lists  are  set  up  in  case  the  proxy  builder  does  not  handle
0168        interaction  by  itself.
0169    4.  We  then  iterate  on  the  various  supported  views  and  add  elements  to  them,
0170        making  sure  that  we  handle  the  case  in  which  those  elements  are  not
0171        unique  among  all  the  views.
0172   */
0173 
0174 void FWEveViewManager::newItem(const FWEventItem* iItem) {
0175   TypeToBuilder::iterator itFind = m_typeToBuilder.find(iItem->purpose());
0176 
0177   if (itFind == m_typeToBuilder.end())
0178     return;
0179 
0180   std::vector<BuilderInfo>& blist = itFind->second;
0181 
0182   std::string bType;
0183   bool bIsSimple;
0184   for (size_t bii = 0, bie = blist.size(); bii != bie; ++bii) {
0185     // 1.
0186     BuilderInfo& info = blist[bii];
0187     info.classType(bType, bIsSimple);
0188     if (bIsSimple) {
0189       unsigned int distance = 1;
0190       edm::TypeWithDict modelType(*(iItem->modelType()->GetTypeInfo()));
0191       if (!FWSimpleRepresentationChecker::inheritsFrom(modelType, bType, distance)) {
0192         // printf("PB does not matche itemType (%s) !!! EDproduct %s %s\n", info.m_name.c_str(), iItem->modelType()->GetTypeInfo()->name(), bType.c_str() );
0193         continue;
0194       }
0195     } else {
0196       std::string itype = iItem->type()->GetTypeInfo()->name();
0197       if (itype != bType) {
0198         // printf("PB does not match modeType (%s)!!! EDproduct %s %s\n", info.m_name.c_str(), itype.c_str(), bType.c_str() );
0199         continue;
0200       }
0201     }
0202 
0203     std::string builderName = info.m_name;
0204     int builderViewBit = info.m_viewBit;
0205 
0206     std::shared_ptr<FWProxyBuilderBase> builder;
0207     try {
0208       builder = std::shared_ptr<FWProxyBuilderBase>{FWProxyBuilderFactory::get()->create(builderName)};
0209 
0210     } catch (std::exception& exc) {
0211       fwLog(fwlog::kWarning)
0212           << "FWEveViewManager::newItem ignoring the following exception (probably edmplugincache mismatch):"
0213           << std::endl
0214           << exc.what();
0215     }
0216     if (!builder)
0217       continue;
0218 
0219     // 2.
0220     // printf("FWEveViewManager::makeProxyBuilderFor NEW builder %s \n", builderName.c_str());
0221 
0222     builder->setItem(iItem);
0223     iItem->changed_.connect(std::bind(&FWEveViewManager::modelChanges, this, std::placeholders::_1));
0224     iItem->goingToBeDestroyed_.connect(std::bind(&FWEveViewManager::removeItem, this, std::placeholders::_1));
0225     iItem->itemChanged_.connect(std::bind(&FWEveViewManager::itemChanged, this, std::placeholders::_1));
0226 
0227     // 3.
0228     // This calud be opaque to the user. I would pass a reference to the m_interactionLists to
0229     // FWProxyBuilderBase::setInteractionList and handle different case differently.
0230     if (builder->willHandleInteraction() == false) {
0231       typedef std::map<const FWEventItem*, FWInteractionList*>::iterator Iterator;
0232       std::pair<Iterator, bool> t = m_interactionLists.insert(std::make_pair(iItem, (FWInteractionList*)nullptr));
0233 
0234       if (t.second == true)
0235         t.first->second = new FWInteractionList(iItem);
0236       //  printf(">>> builder %s add list %p \n", iItem->name().c_str(), il); fflush(stdout);
0237       builder->setInteractionList(t.first->second, iItem->purpose());
0238     }
0239 
0240     builder->setHaveWindow(haveViewForBit(builderViewBit));
0241 
0242     // 4.
0243     for (size_t viewType = 0; viewType < FWViewType::kTypeSize; ++viewType) {
0244       if (((1 << viewType) & builderViewBit) == 0)
0245         continue;
0246 
0247       FWViewType::EType type = (FWViewType::EType)viewType;
0248 
0249       // printf("%s builder %s supportsd view %s \n",  iItem->name().c_str(), builderName.c_str(), FWViewType::idToName(viewType).c_str());
0250       if (builder->havePerViewProduct((FWViewType::EType)viewType)) {
0251         for (size_t i = 0, e = m_views[viewType].size(); i != e; ++i) {
0252           FWEveView* view = m_views[viewType][i].get();
0253           TEveElementList* product = builder->createProduct(type, view->viewContext());
0254           addElements(iItem, view, viewType, product);
0255         }
0256       } else {
0257         TEveElementList* product = builder->createProduct(type, nullptr);
0258 
0259         for (size_t i = 0, e = m_views[viewType].size(); i != e; ++i)
0260           addElements(iItem, m_views[viewType][i].get(), viewType, product);
0261       }
0262     }
0263 
0264     m_builders[builderViewBit].emplace_back(std::move(builder));
0265   }  // loop views
0266 }
0267 
0268 //______________________________________________________________________________
0269 FWViewBase* FWEveViewManager::buildView(TEveWindowSlot* iParent, const std::string& viewName) {
0270   FWViewType::EType type = FWViewType::kTypeSize;
0271   for (int i = 0; i < FWViewType::kTypeSize; ++i) {
0272     if (viewName == FWViewType::idToName(i)) {
0273       type = FWViewType::EType(i);
0274       break;
0275     }
0276   }
0277 
0278   std::shared_ptr<FWEveView> view;
0279   switch (type) {
0280     case FWViewType::k3D:
0281       view.reset(new FW3DView(iParent, type));
0282       break;
0283     case FWViewType::kISpy:
0284       view.reset(new FWISpyView(iParent, type));
0285       break;
0286     case FWViewType::kRhoPhi:
0287     case FWViewType::kRhoZ:
0288     case FWViewType::kRhoPhiPF:
0289       view.reset(new FWRPZView(iParent, type));
0290       break;
0291     case FWViewType::kLego:
0292     case FWViewType::kLegoPFECAL:
0293       view.reset(new FWEveLegoView(iParent, type));
0294       break;
0295     case FWViewType::kLegoHF:
0296       view.reset(new FWHFView(iParent, type));
0297       break;
0298     case FWViewType::kGlimpse:
0299       view.reset(new FWGlimpseView(iParent, type));
0300       break;
0301     default:
0302       break;
0303   }
0304 
0305   m_views[type].push_back(std::shared_ptr<FWEveView>(view));
0306   return finishViewCreate(m_views[type].back());
0307 }
0308 
0309 FWEveView* FWEveViewManager::finishViewCreate(std::shared_ptr<FWEveView> view) {
0310   // printf("new view %s added \n", view->typeName().c_str());
0311   gEve->DisableRedraw();
0312 
0313   // set geometry and calo data
0314   view->setContext(context());
0315 
0316   FWColorManager::setColorSetViewer(view->viewerGL(), context().colorManager()->background());
0317 
0318   // set proxies have a window falg
0319   int viewerBit = 1 << view->typeId();
0320   if (m_views[view->typeId()].size() == 1) {
0321     for (std::map<int, BuilderVec>::iterator i = m_builders.begin(); i != m_builders.end(); ++i) {
0322       int builderViewBit = i->first;
0323       BuilderVec& bv = i->second;
0324       if (viewerBit == (builderViewBit & viewerBit)) {
0325         for (BuilderVec_it bIt = bv.begin(); bIt != bv.end(); ++bIt) {
0326           (*bIt)->setHaveWindow(true);
0327         }
0328       }
0329     }
0330   }
0331 
0332   FWRPZView* rpzView = dynamic_cast<FWRPZView*>(view.get());
0333   for (std::map<int, BuilderVec>::iterator i = m_builders.begin(); i != m_builders.end(); ++i) {
0334     int builderViewBit = i->first;
0335     BuilderVec& bv = i->second;
0336     if (viewerBit == (builderViewBit & viewerBit)) {
0337       for (BuilderVec_it bIt = bv.begin(); bIt != bv.end(); ++bIt) {
0338         // it is ok to call create even for shared productsm since
0339         // builder map key garanties that
0340         TEveElementList* product = (*bIt)->createProduct(view->typeId(), view->viewContext());
0341 
0342         if ((*bIt)->havePerViewProduct((FWViewType::EType)view->typeId())) {
0343           // view owned
0344           (*bIt)->build();
0345           if (rpzView) {
0346             rpzView->importElements(product, (*bIt)->item()->layer(), rpzView->ownedProducts());
0347           } else {
0348             view->ownedProducts()->AddElement(product);
0349           }
0350         } else {
0351           // shared
0352           if (rpzView) {
0353             rpzView->importElements(product, (*bIt)->item()->layer(), rpzView->eventScene());
0354           } else {
0355             view->eventScene()->AddElement(product);
0356           }
0357         }
0358       }
0359     }
0360   }
0361 
0362   view->beingDestroyed_.connect(std::bind(&FWEveViewManager::beingDestroyed, this, std::placeholders::_1));
0363 
0364   view->setupEnergyScale();  // notify PB for energy scale
0365 
0366   gEve->EnableRedraw();
0367   view->viewerGL()->UpdateScene();
0368   gEve->Redraw3D();
0369 
0370   return view.get();
0371 }
0372 
0373 void FWEveViewManager::beingDestroyed(const FWViewBase* vb) {
0374   FWEveView* view = (FWEveView*)vb;
0375   int typeId = view->typeId();
0376 
0377   int viewerBit = 1 << typeId;
0378   int nviews = m_views[typeId].size();
0379   for (std::map<int, BuilderVec>::iterator i = m_builders.begin(); i != m_builders.end(); ++i) {
0380     int builderBit = i->first;
0381     if (viewerBit == (builderBit & viewerBit))  // check only in case if connected
0382     {
0383       BuilderVec& bv = i->second;
0384 
0385       // remove view-owned product
0386       if (viewerBit == (builderBit & viewerBit)) {
0387         for (BuilderVec_it bIt = bv.begin(); bIt != bv.end(); ++bIt)
0388           (*bIt)->removePerViewProduct(view->typeId(), view->viewContext());
0389       }
0390 
0391       // and setup proxy builders have-a-window flag
0392       if (nviews == 1) {
0393         if (!haveViewForBit(builderBit)) {
0394           if (viewerBit == (builderBit & viewerBit)) {
0395             for (BuilderVec_it bIt = bv.begin(); bIt != bv.end(); ++bIt)
0396               (*bIt)->setHaveWindow(false);
0397           }
0398         }
0399       }
0400     }
0401   }
0402 
0403   for (EveViewVec_it i = m_views[typeId].begin(); i != m_views[typeId].end(); ++i) {
0404     if (i->get() == vb) {
0405       m_views[typeId].erase(i);
0406       break;
0407     }
0408   }
0409 }
0410 
0411 //______________________________________________________________________________
0412 
0413 void FWEveViewManager::modelChangesComing() { gEve->DisableRedraw(); }
0414 
0415 void FWEveViewManager::modelChangesDone() { gEve->EnableRedraw(); }
0416 
0417 /** Callback of event item changed_ signal.*/
0418 void FWEveViewManager::modelChanges(const FWModelIds& iIds) {
0419   FWModelId id = *(iIds.begin());
0420   const FWEventItem* item = id.item();
0421 
0422   // in standard case new elements can be build in case of change of visibility
0423   // and in non-standard case (e.g. calo towers) PB's modelChages handles all changes
0424   bool itemHaveWindow = false;
0425   for (std::map<int, BuilderVec>::iterator i = m_builders.begin(); i != m_builders.end(); ++i) {
0426     for (size_t bi = 0, be = i->second.size(); bi != be; ++bi) {
0427       FWProxyBuilderBase* builder = i->second[bi].get();
0428       if (builder->getHaveWindow() && builder->item() == item) {
0429         builder->modelChanges(iIds);
0430         itemHaveWindow = true;
0431       }
0432     }
0433   }
0434 
0435   if (!itemHaveWindow)
0436     return;
0437 
0438   EveSelectionSentry();
0439 
0440   std::map<const FWEventItem*, FWInteractionList*>::iterator it = m_interactionLists.find(item);
0441   if (it != m_interactionLists.end()) {
0442     if (!it->second->empty())
0443       it->second->modelChanges(iIds);
0444   }
0445 }
0446 
0447 /** Callback of itemChanged_ signal.
0448     Iterate over all the builders for all the views and call itemChanged
0449     for any of the builders.
0450     If any of the builder also has at least one view, also update the interaction list.
0451 */
0452 void FWEveViewManager::itemChanged(const FWEventItem* item) {
0453   if (!item)
0454     return;
0455 
0456   bool itemHaveWindow = false;
0457 
0458   for (std::map<int, BuilderVec>::iterator i = m_builders.begin(); i != m_builders.end(); ++i) {
0459     for (size_t bi = 0, be = i->second.size(); bi != be; ++bi) {
0460       FWProxyBuilderBase* builder = i->second[bi].get();
0461 
0462       if (builder->item() != item)
0463         continue;
0464 
0465       builder->itemChanged(item);
0466       itemHaveWindow |= builder->getHaveWindow();
0467     }
0468   }
0469 
0470   if (!itemHaveWindow)
0471     return;
0472 
0473   std::map<const FWEventItem*, FWInteractionList*>::iterator it = m_interactionLists.find(item);
0474   if (it != m_interactionLists.end()) {
0475     if (!it->second->empty())
0476       it->second->itemChanged();
0477   }
0478 }
0479 
0480 /** Remove an item from the given view.
0481   */
0482 void FWEveViewManager::removeItem(const FWEventItem* item) {
0483   EveSelectionSentry();
0484 
0485   std::map<const FWEventItem*, FWInteractionList*>::iterator it = m_interactionLists.find(item);
0486   if (it != m_interactionLists.end()) {
0487     delete it->second;
0488     m_interactionLists.erase(it);
0489   }
0490 
0491   for (std::map<int, BuilderVec>::iterator i = m_builders.begin(); i != m_builders.end(); ++i) {
0492     BuilderVec_it bIt = i->second.begin();
0493     while (bIt != i->second.end()) {
0494       if ((*bIt)->item() == item) {
0495         // TODO caching of proxy builders
0496         (*bIt)->itemBeingDestroyed(item);
0497         bIt = i->second.erase(bIt);
0498       } else {
0499         ++bIt;
0500       }
0501     }
0502   }
0503 }
0504 
0505 void FWEveViewManager::setContext(const fireworks::Context* x) {
0506   FWViewManagerBase::setContext(x);
0507   x->commonPrefs()->getEnergyScale()->parameterChanged_.connect(
0508       std::bind(&FWEveViewManager::globalEnergyScaleChanged, this));
0509   x->commonPrefs()->eventCenterChanged_.connect(std::bind(&FWEveViewManager::eventCenterChanged, this));
0510 }
0511 
0512 void FWEveViewManager::globalEnergyScaleChanged() {
0513   for (int t = 0; t < FWViewType::kTypeSize; ++t) {
0514     for (EveViewVec_it i = m_views[t].begin(); i != m_views[t].end(); ++i) {
0515       if ((*i)->isEnergyScaleGlobal()) {
0516         (*i)->setupEnergyScale();
0517       }
0518     }
0519   }
0520 }
0521 
0522 void FWEveViewManager::eventCenterChanged() {
0523   for (int t = 0; t < FWViewType::kTypeSize; ++t) {
0524     for (EveViewVec_it i = m_views[t].begin(); i != m_views[t].end(); ++i) {
0525       (*i)->setupEventCenter();
0526     }
0527   }
0528 }
0529 
0530 void FWEveViewManager::colorsChanged() {
0531   for (int t = 0; t < FWViewType::kTypeSize; ++t) {
0532     for (EveViewVec_it i = m_views[t].begin(); i != m_views[t].end(); ++i)
0533       (*i)->setBackgroundColor(colorManager().background());
0534   }
0535 }
0536 
0537 //______________________________________________________________________________
0538 void FWEveViewManager::eventBegin() {
0539   // Prevent registration of redraw timer, full redraw is done in
0540   // FWEveViewManager::eventEnd().
0541   gEve->EnforceTimerActive(kTRUE);
0542   gEve->DisableRedraw();
0543 
0544   context().resetMaxEtAndEnergy();
0545 
0546   for (int t = 0; t < FWViewType::kTypeSize; ++t) {
0547     for (EveViewVec_it i = m_views[t].begin(); i != m_views[t].end(); ++i)
0548       (*i)->eventBegin();
0549   }
0550 }
0551 
0552 void FWEveViewManager::eventEnd() {
0553   for (int t = 0; t < FWViewType::kTypeSize; ++t) {
0554     for (EveViewVec_it i = m_views[t].begin(); i != m_views[t].end(); ++i)
0555       (*i)->eventEnd();
0556   }
0557 
0558   // What follows is a copy of TEveManager::DoRedraw3D() with the difference that
0559   // we have full control over execution of GL view rendering. In particular:
0560   // - optionally delay buffer swapping so they can all be swapped together;
0561   // - we could render into FBO once and then use this to be put on screen
0562   //   and saved into an image file.
0563 
0564   {
0565     TEveElement::List_t scenes;
0566     Long64_t key, value;
0567     TExMapIter stamped_elements(gEve->PtrToStampedElements());
0568     while (stamped_elements.Next(key, value)) {
0569       TEveElement* el = reinterpret_cast<TEveElement*>(key);
0570       if (el->GetChangeBits() & TEveElement::kCBVisibility) {
0571         el->CollectSceneParents(scenes);
0572       }
0573     }
0574     gEve->ScenesChanged(scenes);
0575   }
0576 
0577   // Process changes in scenes.
0578   gEve->GetScenes()->ProcessSceneChanges(kFALSE, gEve->PtrToStampedElements());
0579 
0580   // To synchronize buffer swapping set swap_on_render to false.
0581   // Note that this costs 25-40% extra time with 4 views, depending on V-sync settings.
0582   // Tested with NVIDIA 343.22.
0583   const bool swap_on_render = !s_syncAllViews;
0584 
0585   // Loop over viewers, swap buffers if swap_on_render is true.
0586   for (int t = 0; t < FWViewType::kTypeSize; ++t) {
0587     for (EveViewVec_it i = m_views[t].begin(); i != m_views[t].end(); ++i)
0588       (*i)->fwViewerGL()->DrawHiLod(swap_on_render);
0589   }
0590 
0591   // Swap buffers if they were not swapped before.
0592   if (!swap_on_render) {
0593     for (int t = 0; t < FWViewType::kTypeSize; ++t) {
0594       for (EveViewVec_it i = m_views[t].begin(); i != m_views[t].end(); ++i)
0595         (*i)->fwViewerGL()->JustSwap();
0596     }
0597   }
0598 
0599   gEve->GetViewers()->RepaintChangedViewers(kFALSE, kFALSE);
0600 
0601   {
0602     Long64_t key, value;
0603     TExMapIter stamped_elements(gEve->PtrToStampedElements());
0604     while (stamped_elements.Next(key, value)) {
0605       TEveElement* el = reinterpret_cast<TEveElement*>(key);
0606       if (gEve->GetEditor()->GetModel() == el->GetEditorObject("FWEveViewManager::eventEnd"))
0607         gEve->EditElement(el);
0608       TEveGedEditor::ElementChanged(el);
0609 
0610       el->ClearStamps();
0611     }
0612   }
0613   gEve->PtrToStampedElements()->Delete();
0614 
0615   gEve->GetListTree()->ClearViewPort();  // Fix this when several list-trees can be added.
0616 
0617   gEve->EnableRedraw();
0618   gEve->EnforceTimerActive(kFALSE);
0619 }
0620 
0621 //______________________________________________________________________________
0622 
0623 /** Helper function to extract the FWFromEveSelectorBase * from an TEveElement.
0624   */
0625 FWFromEveSelectorBase* getSelector(TEveElement* iElement) {
0626   if (!iElement)
0627     return nullptr;
0628 
0629   //std::cout <<"  non null"<<std::endl;
0630   void* userData = iElement->GetUserData();
0631   //std::cout <<"  user data "<<userData<<std::endl;
0632   if (!userData)
0633     return nullptr;
0634 
0635   //std::cout <<"    have userData"<<std::endl;
0636   //std::cout <<"      calo"<<std::endl;
0637   EveSelectionSentry();
0638   return reinterpret_cast<FWFromEveSelectorBase*>(userData);
0639 }
0640 
0641 void FWEveViewManager::selectionAdded(TEveElement* iElement) {
0642   FWFromEveSelectorBase* selector = getSelector(iElement);
0643   if (selector)
0644     selector->doSelect();
0645 }
0646 
0647 void FWEveViewManager::selectionRemoved(TEveElement* iElement) {
0648   FWFromEveSelectorBase* selector = getSelector(iElement);
0649   if (selector)
0650     selector->doUnselect();
0651 }
0652 
0653 void FWEveViewManager::selectionCleared() { context().selectionManager()->clearSelection(); }
0654 
0655 //
0656 // const member functions
0657 //
0658 
0659 FWTypeToRepresentations FWEveViewManager::supportedTypesAndRepresentations() const {
0660   // needed for add collection GUI
0661   FWTypeToRepresentations returnValue;
0662   const static std::string kFullFrameWorkPBExtension = "FullFramework";
0663   for (TypeToBuilder::const_iterator it = m_typeToBuilder.begin(), itEnd = m_typeToBuilder.end(); it != itEnd; ++it) {
0664     std::vector<BuilderInfo> blist = it->second;
0665     for (size_t bii = 0, bie = blist.size(); bii != bie; ++bii) {
0666       BuilderInfo& info = blist[bii];
0667 
0668       if (context().getHidePFBuilders()) {
0669         const static std::string pfExt = "PF ";
0670         if (std::string::npos != info.m_name.find(pfExt))
0671           continue;
0672       }
0673 
0674       unsigned int bitPackedViews = info.m_viewBit;
0675       bool representsSubPart = (info.m_name.substr(info.m_name.find_first_of('@') - 1, 1) == "!");
0676       size_t extp = info.m_name.rfind(kFullFrameWorkPBExtension);
0677       bool FFOnly = (extp != std::string::npos);
0678 
0679       std::string name;
0680       bool isSimple;
0681       info.classType(name, isSimple);
0682       if (isSimple) {
0683         returnValue.add(std::make_shared<FWSimpleRepresentationChecker>(
0684             name, it->first, bitPackedViews, representsSubPart, FFOnly));
0685       } else {
0686         returnValue.add(std::make_shared<FWEDProductRepresentationChecker>(
0687             name, it->first, bitPackedViews, representsSubPart, FFOnly));
0688       }
0689     }
0690   }
0691   return returnValue;
0692 }
0693 
0694 /** Checks whether any of the views */
0695 bool FWEveViewManager::haveViewForBit(int bit) const {
0696   for (int t = 0; t < FWViewType::kTypeSize; ++t) {
0697     if ((bit & (1 << t)) && !m_views[t].empty())
0698       return true;
0699   }
0700   // printf("have %d view for bit %d \n", haveView, bit);
0701   return false;
0702 }
0703 
0704 void FWEveViewManager::BuilderInfo::classType(std::string& typeName, bool& simple) const {
0705   const std::string kSimple("simple#");
0706   simple = (m_name.substr(0, kSimple.size()) == kSimple);
0707   if (simple) {
0708     typeName = m_name.substr(kSimple.size(), m_name.find_first_of('@') - kSimple.size() - 1);
0709   } else {
0710     typeName = m_name.substr(0, m_name.find_first_of('@') - 1);
0711   }
0712 }
0713 
0714 /*
0715 AMT: temporary workaround for using TEveCaloDataHist instead of
0716 TEveCaloDataVec. 
0717 
0718  */
0719 
0720 #include "TH2F.h"
0721 #include "TAxis.h"
0722 #include "TEveCaloData.h"
0723 
0724 void FWEveViewManager::highlightAdded(TEveElement* iElement) {
0725   bool blocked = gEve->GetHighlight()->BlockSignals(true);
0726 
0727   if (iElement == context().getCaloData()) {
0728     TEveCaloData::vCellId_t& hlist = context().getCaloData()->GetCellsHighlighted();
0729     std::set<TEveCaloData::CellId_t> hset;
0730 
0731     int etaBin, phiBin, w, newPhiBin, tower;
0732     TH2F* hist = context().getCaloData()->GetHist(0);
0733     TAxis* etaAxis = hist->GetXaxis();
0734     int nBinsX = etaAxis->GetNbins() + 2;
0735 
0736     for (TEveCaloData::vCellId_i i = hlist.begin(); i != hlist.end(); ++i) {
0737       hist->GetBinXYZ((*i).fTower, etaBin, phiBin, w);
0738       if (TMath::Abs(etaAxis->GetBinCenter(etaBin)) > 4.71475) {
0739         newPhiBin = ((phiBin + 1) / 4) * 4 - 1;
0740         if (newPhiBin <= 0)
0741           newPhiBin = 71;
0742 
0743         tower = etaBin + newPhiBin * nBinsX;
0744         hset.insert(TEveCaloData::CellId_t(tower, (*i).fSlice, (*i).fFraction));
0745         tower += nBinsX;
0746         hset.insert(TEveCaloData::CellId_t(tower, (*i).fSlice, (*i).fFraction));
0747         tower += nBinsX;
0748 
0749         if (newPhiBin == 71)
0750           tower = etaBin + 1 * nBinsX;
0751 
0752         hset.insert(TEveCaloData::CellId_t(tower, (*i).fSlice, (*i).fFraction));
0753         tower += nBinsX;
0754         hset.insert(TEveCaloData::CellId_t(tower, (*i).fSlice, (*i).fFraction));
0755       } else if (TMath::Abs(etaAxis->GetBinCenter(etaBin)) > 1.747650) {
0756         newPhiBin = ((phiBin + 1) / 2) * 2 - 1;
0757         tower = etaBin + newPhiBin * nBinsX;
0758         hset.insert(TEveCaloData::CellId_t(tower, (*i).fSlice, (*i).fFraction));
0759         tower += nBinsX;
0760         hset.insert(TEveCaloData::CellId_t(tower, (*i).fSlice, (*i).fFraction));
0761       } else {
0762         hset.insert(*i);
0763       }
0764     }
0765 
0766     // edit calo data list
0767     hlist.clear();
0768     for (std::set<TEveCaloData::CellId_t>::iterator it = hset.begin(); it != hset.end(); ++it) {
0769       hlist.push_back(*it);
0770     }
0771     context().getCaloData()->CellSelectionChanged();
0772   }
0773 
0774   gEve->GetHighlight()->BlockSignals(blocked);
0775 }