Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:27:18

0001 // -*- C++ -*-
0002 //
0003 // Package:     Core
0004 // Class  :     FWProxyBuilderBase
0005 //
0006 // Implementation:
0007 //     [Notes on implementation]
0008 //
0009 // Original Author:  Chris Jones, Matevz Tadel, Alja Mrak-Tadel
0010 //         Created:  Thu Mar 18 14:12:00 CET 2010
0011 //
0012 
0013 // system include files
0014 #include <iostream>
0015 #include <functional>
0016 
0017 // user include files
0018 #include "TEveElement.h"
0019 #include "TEveCompound.h"
0020 #include "TEveManager.h"
0021 #include "TEveProjectionManager.h"
0022 #include "TEveSelection.h"
0023 
0024 #include "Fireworks/Core/interface/FWProxyBuilderBase.h"
0025 #include "Fireworks/Core/interface/FWEventItem.h"
0026 #include "Fireworks/Core/interface/FWModelId.h"
0027 #include "Fireworks/Core/interface/FWInteractionList.h"
0028 #include "Fireworks/Core/interface/FWViewContext.h"
0029 #include "Fireworks/Core/interface/fwLog.h"
0030 
0031 //
0032 // constants, enums and typedefs
0033 //
0034 
0035 //
0036 // static data member definitions
0037 //
0038 
0039 //
0040 // constructors and destructor
0041 //
0042 
0043 FWProxyBuilderBase::Product::Product(FWViewType::EType t, const FWViewContext* c)
0044     : m_viewType(t), m_viewContext(c), m_elements(nullptr) {
0045   m_elements = new TEveElementList("ProxyProduct");
0046   m_elements->IncDenyDestroy();
0047 }
0048 
0049 FWProxyBuilderBase::Product::~Product() {
0050   // remove product from projected scene (RhoPhi or RhoZ)
0051   TEveProjectable* pable = dynamic_cast<TEveProjectable*>(m_elements);
0052   // don't have to check cast, because TEveElementList is TEveProjectable
0053   for (TEveProjectable::ProjList_i i = pable->BeginProjecteds(); i != pable->EndProjecteds(); ++i) {
0054     TEveElement* projected = (*i)->GetProjectedAsElement();
0055     (*projected->BeginParents())->RemoveElement(projected);
0056   }
0057 
0058   // remove from 3D scenes
0059   while (m_elements->HasParents()) {
0060     TEveElement* parent = *m_elements->BeginParents();
0061     parent->RemoveElement(m_elements);
0062   }
0063 
0064   m_elements->Annihilate();
0065 }
0066 
0067 //______________________________________________________________________________
0068 
0069 FWProxyBuilderBase::FWProxyBuilderBase()
0070     : m_interactionList(nullptr),
0071       m_item(nullptr),
0072       m_modelsChanged(false),
0073       m_haveWindow(false),
0074       m_mustBuild(true),
0075       m_layer(0) {}
0076 
0077 FWProxyBuilderBase::~FWProxyBuilderBase() { m_products.clear(); }
0078 
0079 //
0080 // member functions
0081 //
0082 
0083 void FWProxyBuilderBase::setItem(const FWEventItem* iItem) { m_item = iItem; }
0084 
0085 void FWProxyBuilderBase::setHaveWindow(bool iFlag) {
0086   bool oldValue = m_haveWindow;
0087   m_haveWindow = iFlag;
0088 
0089   if (iFlag && !oldValue) {
0090     //this is our first view so may need to rerun our building
0091     if (m_mustBuild) {
0092       build();
0093     }
0094   }
0095 }
0096 
0097 void FWProxyBuilderBase::itemBeingDestroyed(const FWEventItem* iItem) {
0098   m_item = nullptr;
0099 
0100   cleanLocal();
0101 
0102   for (Product_it i = m_products.begin(); i != m_products.end(); i++) {
0103     (*i)->m_scaleConnection.disconnect();
0104     delete (*i);
0105   }
0106 
0107   m_products.clear();
0108 }
0109 
0110 void FWProxyBuilderBase::build() {
0111   if (m_item) {
0112     try {
0113       size_t itemSize = m_item->size();  //cashed
0114 
0115       clean();
0116       for (Product_it i = m_products.begin(); i != m_products.end(); ++i) {
0117         //printf("build() %s \n", m_item->name().c_str());
0118         TEveElementList* elms = (*i)->m_elements;
0119         size_t oldSize = elms->NumChildren();
0120 
0121         if (haveSingleProduct()) {
0122           build(m_item, elms, (*i)->m_viewContext);
0123         } else {
0124           buildViewType(m_item, elms, (*i)->m_viewType, (*i)->m_viewContext);
0125         }
0126 
0127         // Project all children of current product.
0128         // If product is not registered into any projection-manager,
0129         // this does nothing.
0130         TEveProjectable* pable = dynamic_cast<TEveProjectable*>(elms);
0131         if (pable->HasProjecteds()) {
0132           // loop projected holders
0133           for (TEveProjectable::ProjList_i i = pable->BeginProjecteds(); i != pable->EndProjecteds(); ++i) {
0134             TEveProjectionManager* pmgr = (*i)->GetManager();
0135             Float_t oldDepth = pmgr->GetCurrentDepth();
0136             pmgr->SetCurrentDepth(item()->layer());
0137             size_t cnt = 0;
0138 
0139             TEveElement* projectedAsElement = (*i)->GetProjectedAsElement();
0140             TEveElement::List_i parentIt = projectedAsElement->BeginChildren();
0141             for (TEveElement::List_i prodIt = elms->BeginChildren(); prodIt != elms->EndChildren(); ++prodIt, ++cnt) {
0142               // reused projected holder
0143               if (cnt < oldSize) {
0144                 if ((*parentIt)->NumChildren()) {
0145                   // update projected (mislleading name)
0146                   for (TEveElement::List_i pci = (*parentIt)->BeginChildren(); pci != (*parentIt)->EndChildren(); pci++)
0147                     pmgr->ProjectChildrenRecurse(*parentIt);
0148                 } else {
0149                   // import projectable
0150                   pmgr->SubImportChildren(*prodIt, *parentIt);
0151                 }
0152 
0153                 ++parentIt;
0154               } else if (cnt < itemSize) {
0155                 // new product holder
0156                 pmgr->SubImportElements(*prodIt, projectedAsElement);
0157               } else {
0158                 break;
0159               }
0160             }
0161             pmgr->SetCurrentDepth(oldDepth);
0162           }
0163         }
0164 
0165         if (m_interactionList && itemSize > oldSize) {
0166           TEveElement::List_i elIt = elms->BeginChildren();
0167           for (size_t cnt = 0; cnt < itemSize; ++cnt, ++elIt) {
0168             if (cnt >= oldSize)
0169               m_interactionList->added(*elIt, cnt);
0170           }
0171         }
0172       }
0173     } catch (const std::runtime_error& iException) {
0174       fwLog(fwlog::kError) << "Caught exception in build function for item " << m_item->name() << ":\n"
0175                            << iException.what() << std::endl;
0176       exit(1);
0177     }
0178   }
0179   m_mustBuild = false;
0180 }
0181 
0182 //______________________________________________________________________________
0183 void FWProxyBuilderBase::modelChanges(const FWModelIds& iIds, Product* p) {
0184   TEveElementList* elms = p->m_elements;
0185   assert(m_item && static_cast<int>(m_item->size()) <= elms->NumChildren() &&
0186          "can not use default modelChanges implementation");
0187 
0188   TEveElement::List_i itElement = elms->BeginChildren();
0189   int index = 0;
0190   for (FWModelIds::const_iterator it = iIds.begin(), itEnd = iIds.end(); it != itEnd; ++it, ++itElement, ++index) {
0191     assert(itElement != elms->EndChildren());
0192     while (index < it->index()) {
0193       ++itElement;
0194       ++index;
0195       assert(itElement != elms->EndChildren());
0196     }
0197     if (visibilityModelChanges(*it, *itElement, p->m_viewType, p->m_viewContext)) {
0198       elms->ProjectChild(*itElement);
0199     } else {
0200       localModelChanges(*it, *itElement, p->m_viewType, p->m_viewContext);
0201     }
0202   }
0203 }
0204 
0205 void FWProxyBuilderBase::modelChanges(const FWModelIds& iIds) {
0206   if (m_haveWindow) {
0207     for (Product_it i = m_products.begin(); i != m_products.end(); ++i) {
0208       modelChanges(iIds, *i);
0209     }
0210     m_modelsChanged = false;
0211   } else {
0212     m_modelsChanged = true;
0213   }
0214 }
0215 
0216 //______________________________________________________________________________
0217 void FWProxyBuilderBase::itemChanged(const FWEventItem* iItem) {
0218   if (iItem->layer() != m_layer)
0219     setProjectionLayer(iItem->layer());
0220 
0221   if (m_haveWindow) {
0222     build();
0223   } else {
0224     m_mustBuild = true;
0225   }
0226   m_modelsChanged = false;
0227 }
0228 
0229 //______________________________________________________________________________
0230 bool FWProxyBuilderBase::canHandle(const FWEventItem& item) {
0231   if (m_item)
0232     return (item.purpose() == m_item->purpose());
0233 
0234   return false;
0235 }
0236 
0237 //______________________________________________________________________________
0238 
0239 TEveElementList* FWProxyBuilderBase::createProduct(const FWViewType::EType viewType, const FWViewContext* viewContext) {
0240   if (havePerViewProduct(viewType) == false && m_products.empty() == false) {
0241     if (haveSingleProduct()) {
0242       return m_products.back()->m_elements;
0243     } else {
0244       for (Product_it i = m_products.begin(); i != m_products.end(); ++i) {
0245         if (viewType == (*i)->m_viewType)
0246           return (*i)->m_elements;
0247       }
0248     }
0249   }
0250 
0251   // printf("new product %s for item %s \n", FWViewType::idToName(viewType).c_str(), item()->name().c_str()); fflush(stdout);
0252 
0253   Product* product = new Product(viewType, viewContext);
0254   m_products.push_back(product);
0255   if (viewContext) {
0256     product->m_scaleConnection =
0257         viewContext->scaleChanged_.connect(std::bind(&FWProxyBuilderBase::scaleChanged, this, std::placeholders::_1));
0258   }
0259 
0260   if (item()) {
0261     // debug info in eve browser
0262     product->m_elements->SetElementName(item()->name().c_str());
0263   }
0264   return product->m_elements;
0265 }
0266 
0267 //______________________________________________________________________________
0268 
0269 void FWProxyBuilderBase::removePerViewProduct(FWViewType::EType type, const FWViewContext* vc) {
0270   for (Product_it i = m_products.begin(); i != m_products.end(); ++i) {
0271     if (havePerViewProduct(type) && (*i)->m_viewContext == vc) {
0272       if ((*i)->m_elements)
0273         (*i)->m_elements->DestroyElements();
0274 
0275       if ((*i)->m_viewContext)
0276         (*i)->m_scaleConnection.disconnect();
0277 
0278       delete (*i);
0279       m_products.erase(i);
0280       break;
0281     }
0282   }
0283 }
0284 
0285 //------------------------------------------------------------------------------
0286 
0287 void FWProxyBuilderBase::setInteractionList(FWInteractionList* l, const std::string& /*purpose*/) {
0288   // Called if willHandleInteraction() returns false. Purpose ignored by default.
0289 
0290   m_interactionList = l;
0291 }
0292 
0293 bool FWProxyBuilderBase::visibilityModelChanges(const FWModelId&,
0294                                                 TEveElement*,
0295                                                 FWViewType::EType,
0296                                                 const FWViewContext*) {
0297   return false;
0298 }
0299 
0300 void FWProxyBuilderBase::localModelChanges(const FWModelId&, TEveElement*, FWViewType::EType, const FWViewContext*) {
0301   // Nothing to be done in base class.
0302   // Visibility, main color and main transparency are handled through FWInteractionList.
0303 }
0304 
0305 void FWProxyBuilderBase::scaleChanged(const FWViewContext* vc) {
0306   for (Product_it i = m_products.begin(); i != m_products.end(); ++i) {
0307     if (havePerViewProduct((*i)->m_viewType) && (*i)->m_viewContext == vc) {
0308       scaleProduct((*i)->m_elements, (*i)->m_viewType, (*i)->m_viewContext);
0309     }
0310   }
0311   gEve->Redraw3D();
0312 }
0313 
0314 void FWProxyBuilderBase::clean() {
0315   // Cleans local common element list.
0316   for (Product_it i = m_products.begin(); i != m_products.end(); ++i) {
0317     if ((*i)->m_elements)
0318       (*i)->m_elements->DestroyElements();
0319   }
0320 
0321   cleanLocal();
0322 }
0323 
0324 void FWProxyBuilderBase::cleanLocal() {
0325   // Cleans local common element list.
0326 }
0327 
0328 void FWProxyBuilderBase::build(const FWEventItem*, TEveElementList*, const FWViewContext*) {
0329   assert(
0330       "virtual build(const FWEventItem*, TEveElementList*, const FWViewContext*) not implemented by inherited class");
0331 }
0332 
0333 void FWProxyBuilderBase::buildViewType(const FWEventItem*, TEveElementList*, FWViewType::EType, const FWViewContext*) {
0334   assert(
0335       "virtual buildViewType(const FWEventItem*, TEveElementList*, FWViewType::EType, const FWViewContext*) not "
0336       "implemented by inherited class");
0337 }
0338 
0339 void FWProxyBuilderBase::setProjectionLayer(float layer) {
0340   m_layer = layer;
0341   for (Product_it pIt = m_products.begin(); pIt != m_products.end(); ++pIt) {
0342     TEveProjectable* pable = static_cast<TEveProjectable*>((*pIt)->m_elements);
0343     for (TEveProjectable::ProjList_i i = pable->BeginProjecteds(); i != pable->EndProjecteds(); ++i)
0344       (*i)->SetDepth(m_layer);
0345   }
0346 }
0347 
0348 //------------------------------------------------------------------------------
0349 
0350 void FWProxyBuilderBase::setupAddElement(TEveElement* el, TEveElement* parent, bool color) const {
0351   setupElement(el, color);
0352   parent->AddElement(el);
0353 }
0354 
0355 /** This method is invoked to setup the per element properties of the various
0356     objects being drawn.
0357   */
0358 void FWProxyBuilderBase::setupElement(TEveElement* el, bool color) const {
0359   el->CSCTakeAnyParentAsMaster();
0360   el->SetPickable(true);
0361 
0362   if (color) {
0363     el->CSCApplyMainColorToMatchingChildren();
0364     el->CSCApplyMainTransparencyToMatchingChildren();
0365     el->SetMainColor(m_item->defaultDisplayProperties().color());
0366     assert((m_item->defaultDisplayProperties().transparency() >= 0) &&
0367            (m_item->defaultDisplayProperties().transparency() <= 100));
0368     el->SetMainTransparency(m_item->defaultDisplayProperties().transparency());
0369   }
0370 }
0371 
0372 //------------------------------------------------------------------------------
0373 
0374 TEveCompound* FWProxyBuilderBase::createCompound(bool set_color, bool propagate_color_to_all_children) const {
0375   TEveCompound* c = new TEveCompound();
0376   c->CSCTakeAnyParentAsMaster();
0377   c->CSCImplySelectAllChildren();
0378   c->SetPickable(true);
0379   if (set_color) {
0380     c->SetMainColor(m_item->defaultDisplayProperties().color());
0381     c->SetMainTransparency(m_item->defaultDisplayProperties().transparency());
0382   }
0383   if (propagate_color_to_all_children) {
0384     c->CSCApplyMainColorToAllChildren();
0385     c->CSCApplyMainTransparencyToAllChildren();
0386   } else {
0387     c->CSCApplyMainColorToMatchingChildren();
0388     c->CSCApplyMainTransparencyToMatchingChildren();
0389   }
0390   return c;
0391 }
0392 
0393 void FWProxyBuilderBase::increaseComponentTransparency(unsigned int index,
0394                                                        TEveElement* holder,
0395                                                        const std::string& name,
0396                                                        Char_t transpOffset) {
0397   // Helper function to increse transparency of certain components.
0398 
0399   Char_t transparency = item()->modelInfo(index).displayProperties().transparency();
0400   Char_t transp = TMath::Min(100, transpOffset + (100 - transpOffset) * transparency / 100);
0401   TEveElement::List_t matches;
0402   holder->FindChildren(matches, name.c_str());
0403   for (TEveElement::List_i m = matches.begin(); m != matches.end(); ++m) {
0404     (*m)->SetMainTransparency(transp);
0405   }
0406 }
0407 
0408 //
0409 // const member functions
0410 //
0411 
0412 const fireworks::Context& FWProxyBuilderBase::context() const { return m_item->context(); }
0413 
0414 int FWProxyBuilderBase::layer() const { return m_item->layer(); }
0415 
0416 //
0417 // static member functions
0418 //
0419 
0420 std::string FWProxyBuilderBase::typeOfBuilder() { return std::string(); }
0421 
0422 bool FWProxyBuilderBase::representsSubPart() { return false; }