/*========================================================================= Program: ParaView Module: vtkSMParaViewPipelineController.cxx Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkSMParaViewPipelineController.h" #include "vtkCommand.h" #include "vtkNew.h" #include "vtkObjectFactory.h" #include "vtkPVProxyDefinitionIterator.h" #include "vtkPVXMLElement.h" #include "vtkSmartPointer.h" #include "vtkSMGlobalPropertiesProxy.h" #include "vtkSMProperty.h" #include "vtkSMPropertyHelper.h" #include "vtkSMPropertyIterator.h" #include "vtkSMPropertyLink.h" #include "vtkSMProxyDefinitionManager.h" #include "vtkSMProxyIterator.h" #include "vtkSMProxyListDomain.h" #include "vtkSMProxyProperty.h" #include "vtkSMProxySelectionModel.h" #include "vtkSMSession.h" #include "vtkSMSessionProxyManager.h" #include "vtkSMSettings.h" #include "vtkSMSourceProxy.h" #include "vtkSMTimeKeeperProxy.h" #include "vtkSMTrace.h" #include "vtkWeakPointer.h" #include #include #include #include #include class vtkSMParaViewPipelineController::vtkInternals { public: typedef std::map TimeStampsMap; TimeStampsMap InitializationTimeStamps; std::set ProxiesBeingUnRegistered; }; namespace { // Used to monitor properties whose domains change. class vtkDomainObserver { std::vector > MonitoredProperties; std::set PropertiesWithModifiedDomains; void DomainModified(vtkObject* sender, unsigned long, void*) { vtkSMProperty* prop = vtkSMProperty::SafeDownCast(sender); if (prop) { this->PropertiesWithModifiedDomains.insert(prop); } } public: vtkDomainObserver() { } ~vtkDomainObserver() { for (size_t cc=0; cc < this->MonitoredProperties.size(); cc++) { this->MonitoredProperties[cc].first->RemoveObserver( this->MonitoredProperties[cc].second); } } void Monitor(vtkSMProperty* prop) { assert(prop != NULL); unsigned long oid = prop->AddObserver(vtkCommand::DomainModifiedEvent, this, &vtkDomainObserver::DomainModified); this->MonitoredProperties.push_back( std::pair(prop, oid)); } const std::set& GetPropertiesWithModifiedDomains() const { return this->PropertiesWithModifiedDomains; } }; // method to create a new proxy safely i.e. not produce warnings if definition // is not available. inline vtkSMProxy* vtkSafeNewProxy(vtkSMSessionProxyManager* pxm, const char* group, const char* name) { if (pxm && pxm->GetPrototypeProxy(group, name)) { return pxm->NewProxy(group, name); } return NULL; } class vtkPrepareForUnregisteringScopedObj { void* Proxy; std::set &ProxiesBeingUnRegistered; public: vtkPrepareForUnregisteringScopedObj(void* proxy, std::set& theset) : Proxy(proxy), ProxiesBeingUnRegistered(theset) { this->ProxiesBeingUnRegistered.insert(this->Proxy); } ~vtkPrepareForUnregisteringScopedObj() { this->ProxiesBeingUnRegistered.erase(this->Proxy); } private: vtkPrepareForUnregisteringScopedObj(const vtkPrepareForUnregisteringScopedObj&); void operator=(const vtkPrepareForUnregisteringScopedObj&); }; } //--------------------------------------------------------------------------------------------------------- // This macros makes it easier to avoid running into unregistering loops due to dependency cycles // when unregistering proxies. Any concrete method that unregisters proxies should simply call this macro. #define PREPARE_FOR_UNREGISTERING(arg)\ if (!arg) { return false; } \ if (this->Internals->ProxiesBeingUnRegistered.find(arg) != this->Internals->ProxiesBeingUnRegistered.end()) \ { \ return true; \ } \ vtkPrepareForUnregisteringScopedObj __tmp(arg, this->Internals->ProxiesBeingUnRegistered); vtkObjectFactoryNewMacro(vtkSMParaViewPipelineController); //---------------------------------------------------------------------------- vtkSMParaViewPipelineController::vtkSMParaViewPipelineController() : Internals(new vtkSMParaViewPipelineController::vtkInternals()) { } //---------------------------------------------------------------------------- vtkSMParaViewPipelineController::~vtkSMParaViewPipelineController() { delete this->Internals; this->Internals = NULL; } //---------------------------------------------------------------------------- vtkStdString vtkSMParaViewPipelineController::GetHelperProxyGroupName(vtkSMProxy* proxy) { assert(proxy != NULL); std::ostringstream groupnamestr; groupnamestr << "pq_helper_proxies." << proxy->GetGlobalIDAsString(); return groupnamestr.str(); } //---------------------------------------------------------------------------- vtkSMProxy* vtkSMParaViewPipelineController::FindProxy( vtkSMSessionProxyManager* pxm, const char* reggroup, const char* xmlgroup, const char* xmltype) { return pxm? pxm->FindProxy(reggroup, xmlgroup, xmltype) : NULL; } //---------------------------------------------------------------------------- bool vtkSMParaViewPipelineController::CreateProxiesForProxyListDomains( vtkSMProxy* proxy) { assert(proxy != NULL); vtkSmartPointer iter; iter.TakeReference(proxy->NewPropertyIterator()); for (iter->Begin(); !iter->IsAtEnd(); iter->Next()) { vtkSMProxyListDomain* pld = iter->GetProperty()? vtkSMProxyListDomain::SafeDownCast(iter->GetProperty()->FindDomain("vtkSMProxyListDomain")) : NULL; if (pld) { pld->CreateProxies(proxy->GetSessionProxyManager()); for (unsigned int cc=0, max=pld->GetNumberOfProxies(); cc < max; cc++) { this->PreInitializeProxy(pld->GetProxy(cc)); } // this is unnecessary here. only done for CompoundSourceProxy instances. // those proxies, we generally skip calling "reset" on in // PostInitializeProxy(). However, for properties that have proxy // list domains, we need to reset them (e.g ProbeLine filter). iter->GetProperty()->ResetToDomainDefaults(); } } return true; } //---------------------------------------------------------------------------- void vtkSMParaViewPipelineController::RegisterProxiesForProxyListDomains( vtkSMProxy* proxy) { assert(proxy != NULL); vtkSMSessionProxyManager* pxm = proxy->GetSessionProxyManager(); std::string groupname = this->GetHelperProxyGroupName(proxy); vtkSmartPointer iter; iter.TakeReference(proxy->NewPropertyIterator()); for (iter->Begin(); !iter->IsAtEnd(); iter->Next()) { vtkSMProxyListDomain* pld = iter->GetProperty()? vtkSMProxyListDomain::SafeDownCast(iter->GetProperty()->FindDomain("vtkSMProxyListDomain")) : NULL; if (!pld) { continue; } for (unsigned int cc=0, max=pld->GetNumberOfProxies(); cc < max; cc++) { vtkSMProxy* plproxy = pld->GetProxy(cc); // Handle proxy-list hints. this->ProcessProxyListProxyHints(proxy, plproxy); this->PostInitializeProxy(plproxy); pxm->RegisterProxy(groupname.c_str(), iter->GetKey(), plproxy); } } } //---------------------------------------------------------------------------- bool vtkSMParaViewPipelineController::SetupGlobalPropertiesLinks(vtkSMProxy* proxy) { assert(proxy != NULL); vtkSMSessionProxyManager* pxm = proxy->GetSessionProxyManager(); vtkSmartPointer iter; iter.TakeReference(proxy->NewPropertyIterator()); for (iter->Begin(); !iter->IsAtEnd(); iter->Next()) { vtkSMProperty* prop = iter->GetProperty(); assert(prop); vtkPVXMLElement* linkHint = prop->GetHints()? prop->GetHints()->FindNestedElementByName("GlobalPropertyLink") : NULL; if (linkHint) { std::string type = linkHint->GetAttributeOrEmpty("type"); std::string property = linkHint->GetAttributeOrEmpty("property"); if (type.empty() || property.empty()) { vtkWarningMacro("Invalid GlobalPropertyLink hint."); continue; } vtkSMGlobalPropertiesProxy* gpproxy = vtkSMGlobalPropertiesProxy::SafeDownCast( pxm->GetProxy("global_properties", type.c_str())); if (!gpproxy) { continue; } if (!gpproxy->Link(property.c_str(), proxy, iter->GetKey())) { vtkWarningMacro("Failed to setup GlobalPropertyLink."); } } // Check for PropertyLinks linkHint = prop->GetHints()? prop->GetHints()->FindNestedElementByName("PropertyLink") : NULL; if (linkHint) { const char* sourceGroupName = linkHint->GetAttributeOrEmpty("group"); const char* sourceProxyName = linkHint->GetAttributeOrEmpty("proxy"); const char* sourcePropertyName = linkHint->GetAttributeOrEmpty("property"); if (!sourceGroupName || !sourceProxyName || !sourcePropertyName) { continue; } vtkSMProxy* sourceProxy = pxm->GetProxy(sourceGroupName, sourceProxyName); if (!sourceProxy) { continue; } vtkSMProperty* sourceProperty = sourceProxy->GetProperty(sourcePropertyName); if (sourceProperty) { sourceProperty->AddLinkedProperty(prop); } else { vtkWarningMacro(<< "No source property with group \"" << sourceGroupName << "\", proxy \"" << sourceProxyName << "\", property \"" << sourcePropertyName << "\" exists. Linking not performed.") } } } return true; } namespace vtkSMParaViewPipelineControllerNS { //--------------------------------------------------------------------------- class vtkSMLinkObserver : public vtkCommand { public: vtkWeakPointer Output; typedef vtkCommand Superclass; virtual const char* GetClassNameInternal() const { return "vtkSMLinkObserver"; } static vtkSMLinkObserver* New() { return new vtkSMLinkObserver(); } virtual void Execute(vtkObject* caller, unsigned long event, void* calldata) { (void)event; (void)calldata; vtkSMProperty* input = vtkSMProperty::SafeDownCast(caller); if (input && this->Output) { // this will copy both checked and unchecked property values. this->Output->Copy(input); } } static void LinkProperty(vtkSMProperty* input, vtkSMProperty* output) { if (input && output) { vtkSMLinkObserver* observer = vtkSMLinkObserver::New(); observer->Output = output; input->AddObserver(vtkCommand::PropertyModifiedEvent, observer); input->AddObserver(vtkCommand::UncheckedPropertyModifiedEvent, observer); observer->FastDelete(); output->Copy(input); } } }; } //---------------------------------------------------------------------------- void vtkSMParaViewPipelineController::ProcessProxyListProxyHints( vtkSMProxy* parent, vtkSMProxy* plproxy) { vtkPVXMLElement* proxyListElement = plproxy->GetHints()? plproxy->GetHints()->FindNestedElementByName("ProxyList") : NULL; if (!proxyListElement) { return; } for (unsigned int cc=0, max = proxyListElement->GetNumberOfNestedElements(); cc < max; ++cc) { vtkPVXMLElement* child = proxyListElement->GetNestedElement(cc); if (child && child->GetName() && strcmp(child->GetName(), "Link") == 0) { const char* name = child->GetAttribute("name"); const char* linked_with = child->GetAttribute("with_property"); if (name && linked_with) { vtkSMParaViewPipelineControllerNS::vtkSMLinkObserver::LinkProperty( parent->GetProperty(linked_with), plproxy->GetProperty(name)); } } } } //---------------------------------------------------------------------------- bool vtkSMParaViewPipelineController::CreateAnimationHelpers(vtkSMProxy* proxy) { vtkSMSourceProxy* source = vtkSMSourceProxy::SafeDownCast(proxy); if (!source) { return false; } assert(proxy != NULL); vtkSMSessionProxyManager* pxm = proxy->GetSessionProxyManager(); std::string groupname = this->GetHelperProxyGroupName(proxy); for (unsigned int cc=0, max=source->GetNumberOfOutputPorts(); cc < max; cc++) { vtkSmartPointer helper; helper.TakeReference(vtkSafeNewProxy(pxm, "misc", "RepresentationAnimationHelper")); if (helper) // since this is optional { this->PreInitializeProxy(helper); vtkSMPropertyHelper(helper, "Source").Set(proxy); this->PostInitializeProxy(helper); helper->UpdateVTKObjects(); // yup, all are registered under same name. pxm->RegisterProxy( groupname.c_str(), "RepresentationAnimationHelper", helper); } } return true; } //---------------------------------------------------------------------------- bool vtkSMParaViewPipelineController::InitializeSession(vtkSMSession* session) { assert(session != NULL); vtkSMSessionProxyManager* pxm = session->GetSessionProxyManager(); assert(pxm); //--------------------------------------------------------------------------- // If the session is a collaborative session, we need to fetch the state from // server before we start creating "essential" proxies. This is a no-op if not // a collaborative session. pxm->UpdateFromRemote(); //--------------------------------------------------------------------------- // Setup selection models used to track active view/active proxy. vtkSMProxySelectionModel* selmodel = pxm->GetSelectionModel("ActiveSources"); if (selmodel == NULL) { selmodel = vtkSMProxySelectionModel::New(); pxm->RegisterSelectionModel("ActiveSources", selmodel); selmodel->FastDelete(); } selmodel = pxm->GetSelectionModel("ActiveView"); if (selmodel == NULL) { selmodel = vtkSMProxySelectionModel::New(); pxm->RegisterSelectionModel("ActiveView", selmodel); selmodel->FastDelete(); } //--------------------------------------------------------------------------- // Create the timekeeper if none exists. vtkSmartPointer timeKeeper = this->FindTimeKeeper(session); if (!timeKeeper) { timeKeeper.TakeReference(vtkSafeNewProxy(pxm, "misc", "TimeKeeper")); if (!timeKeeper) { vtkErrorMacro("Failed to create 'TimeKeeper' proxy. "); return false; } this->InitializeProxy(timeKeeper); timeKeeper->UpdateVTKObjects(); pxm->RegisterProxy("timekeeper", timeKeeper); } //--------------------------------------------------------------------------- // Create the animation-scene (optional) vtkSMProxy* animationScene = this->GetAnimationScene(session); if (animationScene) { // create time-animation track (optional) this->GetTimeAnimationTrack(animationScene); } //--------------------------------------------------------------------------- // Setup global settings/state for the visualization state. this->UpdateSettingsProxies(session); //--------------------------------------------------------------------------- // Setup color palette and proxies for other global property groups (optional) vtkSMProxy* proxy = pxm->GetProxy("global_properties", "ColorPalette"); if (!proxy) { proxy = vtkSafeNewProxy(pxm, "misc", "ColorPalette"); if (proxy) { this->InitializeProxy(proxy); pxm->RegisterProxy("global_properties", "ColorPalette", proxy); proxy->UpdateVTKObjects(); proxy->Delete(); } } return true; } //---------------------------------------------------------------------------- vtkSMProxy* vtkSMParaViewPipelineController::FindTimeKeeper(vtkSMSession* session) { assert(session != NULL); vtkSMSessionProxyManager* pxm = session->GetSessionProxyManager(); assert(pxm); return this->FindProxy(pxm, "timekeeper", "misc", "TimeKeeper"); } //---------------------------------------------------------------------------- vtkSMProxy* vtkSMParaViewPipelineController::FindAnimationScene(vtkSMSession* session) { assert(session != NULL); vtkSMSessionProxyManager* pxm = session->GetSessionProxyManager(); assert(pxm); return this->FindProxy(pxm, "animation", "animation", "AnimationScene"); } //---------------------------------------------------------------------------- vtkSMProxy* vtkSMParaViewPipelineController::GetAnimationScene(vtkSMSession* session) { assert(session != NULL); vtkSMSessionProxyManager* pxm = session->GetSessionProxyManager(); assert(pxm); vtkSMProxy* timeKeeper = this->FindTimeKeeper(session); if (!timeKeeper) { return NULL; } vtkSmartPointer animationScene = this->FindAnimationScene(session); if (!animationScene) { animationScene.TakeReference(vtkSafeNewProxy(pxm, "animation", "AnimationScene")); if (animationScene) { this->PreInitializeProxy(animationScene); vtkSMPropertyHelper(animationScene, "TimeKeeper").Set(timeKeeper); this->PostInitializeProxy(animationScene); animationScene->UpdateVTKObjects(); pxm->RegisterProxy("animation", animationScene); } } return animationScene.GetPointer(); } //---------------------------------------------------------------------------- vtkSMProxy* vtkSMParaViewPipelineController::FindTimeAnimationTrack(vtkSMProxy* scene) { if (!scene) { return NULL; } vtkSMProxy* timeKeeper = this->FindTimeKeeper(scene->GetSession()); if (!timeKeeper) { return NULL; } vtkSMPropertyHelper helper(scene, "Cues", /*quiet*/ true); for (unsigned int cc=0, max=helper.GetNumberOfElements(); cc < max; cc++) { vtkSMProxy* cue = helper.GetAsProxy(cc); if (cue && cue->GetXMLName() && strcmp(cue->GetXMLName(), "TimeAnimationCue") == 0 && vtkSMPropertyHelper(cue, "AnimatedProxy").GetAsProxy() == timeKeeper) { vtkSMPropertyHelper pnameHelper(cue, "AnimatedPropertyName"); if (pnameHelper.GetAsString(0) && strcmp(pnameHelper.GetAsString(0), "Time") == 0) { return cue; } } } return NULL; } //---------------------------------------------------------------------------- vtkSMProxy* vtkSMParaViewPipelineController::GetTimeAnimationTrack(vtkSMProxy* scene) { vtkSmartPointer cue = this->FindTimeAnimationTrack(scene); if (cue || !scene) { return cue; } vtkSMProxy* timeKeeper = this->FindTimeKeeper(scene->GetSession()); if (!timeKeeper) { return NULL; } vtkSMSessionProxyManager* pxm = scene->GetSessionProxyManager(); assert(pxm); cue.TakeReference(vtkSafeNewProxy(pxm, "animation", "TimeAnimationCue")); if (!cue) { return NULL; } this->PreInitializeProxy(cue); vtkSMPropertyHelper(cue, "AnimatedProxy").Set(timeKeeper); vtkSMPropertyHelper(cue, "AnimatedPropertyName").Set("Time"); this->PostInitializeProxy(cue); cue->UpdateVTKObjects(); pxm->RegisterProxy("animation", cue); vtkSMPropertyHelper(scene, "Cues").Add(cue); scene->UpdateVTKObjects(); return cue; } //---------------------------------------------------------------------------- bool vtkSMParaViewPipelineController::RegisterPipelineProxy( vtkSMProxy* proxy, const char* proxyname) { if (!proxy) { return false; } SM_SCOPED_TRACE(RegisterPipelineProxy).arg("proxy", proxy); // Create animation helpers for this proxy. this->CreateAnimationHelpers(proxy); // Now register the proxy itself. // If proxyname is NULL, the proxy manager makes up a name. proxy->GetSessionProxyManager()->RegisterProxy("sources", proxyname, proxy); // Register proxy with TimeKeeper. vtkSMProxy* timeKeeper = this->FindTimeKeeper(proxy->GetSession()); vtkSMTimeKeeperProxy::AddTimeSource(timeKeeper, proxy, /*suppress_input*/ ( proxy->GetProperty("TimestepValues") != NULL || proxy->GetProperty("TimeRange") != NULL)); // Make the proxy active. vtkSMProxySelectionModel* selmodel = proxy->GetSessionProxyManager()->GetSelectionModel("ActiveSources"); assert(selmodel != NULL); selmodel->SetCurrentProxy(proxy, vtkSMProxySelectionModel::CLEAR_AND_SELECT); return true; } //---------------------------------------------------------------------------- bool vtkSMParaViewPipelineController::UnRegisterPipelineProxy(vtkSMProxy* proxy) { PREPARE_FOR_UNREGISTERING(proxy); vtkSMSessionProxyManager* pxm = proxy->GetSessionProxyManager(); const char* _proxyname = pxm->GetProxyName("sources", proxy); if (_proxyname == NULL) { return false; } SM_SCOPED_TRACE(Delete).arg("proxy", proxy); const std::string proxyname(_proxyname); // ensure proxy is no longer active. vtkSMProxySelectionModel* selmodel = pxm->GetSelectionModel("ActiveSources"); assert(selmodel != NULL); if (selmodel->GetCurrentProxy() == proxy) { selmodel->SetCurrentProxy(NULL, vtkSMProxySelectionModel::CLEAR_AND_SELECT); } // remove proxy from TimeKeeper. vtkSMProxy* timeKeeper = this->FindTimeKeeper(proxy->GetSession()); vtkSMTimeKeeperProxy::RemoveTimeSource(timeKeeper, proxy, /*unsuppress_input*/ ( proxy->GetProperty("TimestepValues") != NULL || proxy->GetProperty("TimeRange") != NULL)); // unregister dependencies. this->UnRegisterDependencies(proxy); // this will remove both proxy-list-domain helpers and animation helpers. this->FinalizeProxy(proxy); // unregister the proxy. pxm->UnRegisterProxy("sources", proxyname.c_str(), proxy); return true; } //---------------------------------------------------------------------------- bool vtkSMParaViewPipelineController::RegisterViewProxy( vtkSMProxy* proxy, const char* proxyname) { if (!proxy) { return false; } SM_SCOPED_TRACE(RegisterViewProxy).arg("proxy", proxy); // Now register the proxy itself. proxy->GetSessionProxyManager()->RegisterProxy("views", proxyname, proxy); // Register proxy with TimeKeeper. vtkSMProxy* timeKeeper = this->FindTimeKeeper(proxy->GetSession()); vtkSMPropertyHelper(timeKeeper, "Views").Add(proxy); timeKeeper->UpdateVTKObjects(); // Register proxy with AnimationScene (optional) vtkSMProxy* scene = this->GetAnimationScene(proxy->GetSession()); if (scene) { vtkSMPropertyHelper(scene, "ViewModules").Add(proxy); scene->UpdateVTKObjects(); } // Make the proxy active. vtkSMProxySelectionModel* selmodel = proxy->GetSessionProxyManager()->GetSelectionModel("ActiveView"); assert(selmodel != NULL); selmodel->SetCurrentProxy(proxy, vtkSMProxySelectionModel::CLEAR_AND_SELECT); return true; } //---------------------------------------------------------------------------- bool vtkSMParaViewPipelineController::UnRegisterViewProxy( vtkSMProxy* proxy, bool unregister_representations/*=true*/) { PREPARE_FOR_UNREGISTERING(proxy); vtkSMSessionProxyManager* pxm = proxy->GetSessionProxyManager(); const char* _proxyname = pxm->GetProxyName("views", proxy); if (_proxyname == NULL) { return false; } SM_SCOPED_TRACE(Delete).arg("proxy", proxy); const std::string proxyname(_proxyname); // ensure proxy is no longer active. vtkSMProxySelectionModel* selmodel = pxm->GetSelectionModel("ActiveView"); assert(selmodel != NULL); if (selmodel->GetCurrentProxy() == proxy) { selmodel->SetCurrentProxy(NULL, vtkSMProxySelectionModel::CLEAR_AND_SELECT); } // remove proxy from AnimationScene (optional) vtkSMProxy* scene = this->GetAnimationScene(proxy->GetSession()); if (scene) { vtkSMPropertyHelper(scene, "ViewModules").Remove(proxy); scene->UpdateVTKObjects(); } // remove proxy from TimeKeeper. vtkSMProxy* timeKeeper = this->FindTimeKeeper(proxy->GetSession()); vtkSMPropertyHelper(timeKeeper, "Views").Remove(proxy); timeKeeper->UpdateVTKObjects(); // remove all representation proxies. const char* pnames[]={"Representations", "HiddenRepresentations", "Props", "HiddenProps", NULL}; for (int index=0; unregister_representations && (pnames[index] != NULL); ++index) { vtkSMProperty* prop = proxy->GetProperty(pnames[index]); if (prop == NULL) { continue; } typedef std::vector > proxyvectortype; proxyvectortype reprs; vtkSMPropertyHelper helper(prop); for (unsigned int cc=0, max=helper.GetNumberOfElements(); cc < max ; ++cc) { reprs.push_back(helper.GetAsProxy(cc)); } for (proxyvectortype::iterator iter=reprs.begin(), end=reprs.end(); iter!=end; ++iter) { if (iter->GetPointer()) { this->UnRegisterProxy(iter->GetPointer()); } } } // unregister dependencies. this->UnRegisterDependencies(proxy); // this will remove both proxy-list-domain helpers and animation helpers. this->FinalizeProxy(proxy); pxm->UnRegisterProxy("views", proxyname.c_str(), proxy); return true; } //---------------------------------------------------------------------------- bool vtkSMParaViewPipelineController::RegisterRepresentationProxy(vtkSMProxy* proxy) { if (!proxy) { return false; } // Register the proxy itself. proxy->GetSessionProxyManager()->RegisterProxy("representations", proxy); return true; } //---------------------------------------------------------------------------- bool vtkSMParaViewPipelineController::UnRegisterRepresentationProxy(vtkSMProxy* proxy) { PREPARE_FOR_UNREGISTERING(proxy); vtkSMSessionProxyManager* pxm = proxy->GetSessionProxyManager(); std::string groupname("representations"); const char* _proxyname = pxm->GetProxyName(groupname.c_str(), proxy); if (_proxyname == NULL) { groupname = "scalar_bars"; _proxyname = pxm->GetProxyName(groupname.c_str(), proxy); if (_proxyname == NULL) { return false; } } SM_SCOPED_TRACE(Delete).arg("proxy", proxy); const std::string proxyname(_proxyname); //--------------------------------------------------------------------------- // remove the representation from any views. typedef std::vector > viewsvector; viewsvector views; for (unsigned int cc=0, max=proxy->GetNumberOfConsumers(); cc < max; cc++) { vtkSMProxy* consumer = proxy->GetConsumerProxy(cc); consumer = consumer? consumer->GetTrueParentProxy() : NULL; if (consumer && consumer->IsA("vtkSMViewProxy") && proxy->GetConsumerProperty(cc)) { views.push_back( std::pair( consumer, proxy->GetConsumerProperty(cc))); } } for (viewsvector::iterator iter=views.begin(), max=views.end(); iter != max; ++iter) { if (iter->first && iter->second) { vtkSMPropertyHelper(iter->second).Remove(proxy); iter->first->UpdateVTKObjects(); } } // unregister dependencies. this->UnRegisterDependencies(proxy); // this will remove both proxy-list-domain helpers and animation helpers. this->FinalizeProxy(proxy); proxy->GetSessionProxyManager()->UnRegisterProxy( groupname.c_str(), proxyname.c_str(), proxy); return true; } //---------------------------------------------------------------------------- bool vtkSMParaViewPipelineController::RegisterColorTransferFunctionProxy( vtkSMProxy* proxy, const char* proxyname) { if (!proxy) { return false; } proxy->GetSessionProxyManager()->RegisterProxy( "lookup_tables", proxyname, proxy); return true; } //---------------------------------------------------------------------------- bool vtkSMParaViewPipelineController::RegisterOpacityTransferFunction( vtkSMProxy* proxy, const char* proxyname) { if (!proxy) { return false; } proxy->GetSessionProxyManager()->RegisterProxy( "piecewise_functions", proxyname, proxy); return true; } //---------------------------------------------------------------------------- bool vtkSMParaViewPipelineController::RegisterAnimationProxy(vtkSMProxy* proxy) { if (!proxy) { return false; } proxy->GetSessionProxyManager()->RegisterProxy("animation", proxy); return true; } //---------------------------------------------------------------------------- bool vtkSMParaViewPipelineController::UnRegisterAnimationProxy(vtkSMProxy* proxy) { PREPARE_FOR_UNREGISTERING(proxy); vtkSMSessionProxyManager* pxm = proxy->GetSessionProxyManager(); const char* _proxyname = pxm->GetProxyName("animation", proxy); if (_proxyname == NULL) { return false; } SM_SCOPED_TRACE(Delete).arg("proxy", proxy); const std::string proxyname(_proxyname); //--------------------------------------------------------------------------- // Animation proxies are typically added to some other animation proxy. We // need to remove it from that proxy. typedef std::pair, vtkWeakPointer > proxypairitemtype; typedef std::vector proxypairvectortype; proxypairvectortype consumers; for (unsigned int cc=0, max=proxy->GetNumberOfConsumers(); ccGetConsumerProxy(cc); consumer = consumer? consumer->GetTrueParentProxy() : NULL; if (proxy->GetConsumerProperty(cc) && consumer && consumer->GetXMLGroup() && strcmp(consumer->GetXMLGroup(), "animation") ==0) { consumers.push_back(proxypairitemtype(consumer, proxy->GetConsumerProperty(cc))); } } for (proxypairvectortype::iterator iter=consumers.begin(), max=consumers.end(); iter != max; ++iter) { if (iter->first && iter->second) { vtkSMPropertyHelper(iter->second).Remove(proxy); iter->first->UpdateVTKObjects(); } } //--------------------------------------------------------------------------- // destroy keyframes, if there are any. typedef std::vector > proxyvectortype; proxyvectortype keyframes; if (vtkSMProperty* kfProperty = proxy->GetProperty("KeyFrames")) { vtkSMPropertyHelper helper(kfProperty); for (unsigned int cc=0, max=helper.GetNumberOfElements(); ccUnRegisterDependencies(proxy); // this will remove both proxy-list-domain helpers and animation helpers. this->FinalizeProxy(proxy); pxm->UnRegisterProxy("animation", proxyname.c_str(), proxy); // now destroy all keyframe proxies. for (proxyvectortype::iterator iter=keyframes.begin(), max=keyframes.end(); iter != max;++iter) { if (iter->GetPointer()) { this->UnRegisterProxy(iter->GetPointer()); } } return true; } //---------------------------------------------------------------------------- void vtkSMParaViewPipelineController::UpdateSettingsProxies(vtkSMSession* session) { // Set up the settings proxies vtkSMSessionProxyManager* pxm = session->GetSessionProxyManager(); vtkSMProxyDefinitionManager* pdm = pxm->GetProxyDefinitionManager(); vtkPVProxyDefinitionIterator* iter = pdm->NewSingleGroupIterator( "settings" ); for (iter->GoToFirstItem(); !iter->IsDoneWithTraversal(); iter->GoToNextItem()) { vtkSMProxy* proxy = pxm->GetProxy(iter->GetGroupName(), iter->GetProxyName()); if (!proxy) { proxy = vtkSafeNewProxy(pxm, iter->GetGroupName(), iter->GetProxyName()); if (proxy) { this->InitializeProxy(proxy); if (strcmp(iter->GetProxyName(), "RenderViewSettings") == 0) { this->HandleLZ4Issue(proxy); } pxm->RegisterProxy(iter->GetGroupName(), iter->GetProxyName(), proxy); proxy->UpdateVTKObjects(); proxy->Delete(); } } } iter->Delete(); } //---------------------------------------------------------------------------- bool vtkSMParaViewPipelineController::PreInitializeProxy(vtkSMProxy* proxy) { if (!proxy) { return false; } // 1. Load XML defaults // (already done by NewProxy() call). // 2. Create proxies for proxy-list domains. if (!this->CreateProxiesForProxyListDomains(proxy)) { return false; } // 3. Process global properties hints. if (!this->SetupGlobalPropertiesLinks(proxy)) { return false; } // 4. Load property values from Settings. vtkSMSettings * settings = vtkSMSettings::GetInstance(); settings->GetProxySettings(proxy); // Now, update the initialization time. this->Internals->InitializationTimeStamps[proxy].Modified(); // Note: we need to be careful with *** vtkSMCompoundSourceProxy *** return true; } //---------------------------------------------------------------------------- unsigned long vtkSMParaViewPipelineController::GetInitializationTime(vtkSMProxy* proxy) { vtkInternals::TimeStampsMap::iterator titer = this->Internals->InitializationTimeStamps.find(proxy); return (titer == this->Internals->InitializationTimeStamps.end()? 0: titer->second); } //---------------------------------------------------------------------------- bool vtkSMParaViewPipelineController::PostInitializeProxy(vtkSMProxy* proxy) { if (!proxy) { return false; } vtkInternals::TimeStampsMap::iterator titer = this->Internals->InitializationTimeStamps.find(proxy); if (titer == this->Internals->InitializationTimeStamps.end()) { vtkErrorMacro( "PostInitializeProxy must only be called after PreInitializeProxy"); return false; } assert(titer != this->Internals->InitializationTimeStamps.end()); vtkTimeStamp ts = titer->second; this->Internals->InitializationTimeStamps.erase(titer); // ensure everything is up-to-date. proxy->UpdateVTKObjects(); // FIXME: need to figure out how we should really deal with this. // We don't reset properties on custom filter. if (!proxy->IsA("vtkSMCompoundSourceProxy")) { if (vtkSMSourceProxy* sourceProxy = vtkSMSourceProxy::SafeDownCast(proxy)) { // Since domains depend on information properties, it's essential we update // property information first. if (sourceProxy->GetNumberOfOutputPorts() > 0) { // This is only done for non-writers, or non-sinks. sourceProxy->UpdatePipelineInformation(); } } // Reset property values using domains. However, this should only be done for // properties that were not modified between the PreInitializePipelineProxy and // PostInitializePipelineProxy calls. vtkSmartPointer iter; iter.TakeReference(proxy->NewPropertyIterator()); // iterate over properties and reset them to default. if any property says its // domain is modified after we reset it, we need to reset it again since its // default may have changed. vtkDomainObserver observer; for (iter->Begin(); !iter->IsAtEnd(); iter->Next()) { vtkSMProperty* smproperty = iter->GetProperty(); if ((smproperty->GetMTime() > ts) || smproperty->GetInformationOnly() || // doesn't make sense to set property values for internal properties. smproperty->GetIsInternal()) { // Property was modified between since the PreInitializeProxy() call. We // leave it untouched. continue; } vtkPVXMLElement* propHints = smproperty->GetHints(); if (propHints && propHints->FindNestedElementByName("NoDefault")) { // Don't reset properties that request overriding of the default mechanism. continue; } observer.Monitor(iter->GetProperty()); iter->GetProperty()->ResetToDomainDefaults(); } const std::set &props = observer.GetPropertiesWithModifiedDomains(); for (std::set::const_iterator siter = props.begin(); siter != props.end(); ++siter) { (*siter)->ResetToDomainDefaults(); } proxy->UpdateVTKObjects(); } // Register proxies created for proxy list domains. this->RegisterProxiesForProxyListDomains(proxy); return true; } //---------------------------------------------------------------------------- bool vtkSMParaViewPipelineController::FinalizeProxy(vtkSMProxy* proxy) { if (!proxy) { return false; } //--------------------------------------------------------------------------- // Unregister all helper proxies. This will "unregister" all the helper // proxies which ensures that any "dependent" proxies for those helpers // also get removed. std::string groupname = this->GetHelperProxyGroupName(proxy); typedef std::pair > proxymapitemtype; typedef std::vector proxymaptype; proxymaptype proxymap; vtkSMSessionProxyManager* pxm = proxy->GetSessionProxyManager(); { vtkNew iter; iter->SetSessionProxyManager(pxm); iter->SetModeToOneGroup(); for (iter->Begin(groupname.c_str()); !iter->IsAtEnd(); iter->Next()) { proxymap.push_back(proxymapitemtype( iter->GetKey(), iter->GetProxy())); } } for (proxymaptype::iterator iter = proxymap.begin(), end = proxymap.end(); iter != end; ++iter) { if (iter->second) { // remove any dependencies for this proxy. this->UnRegisterDependencies(iter->second); // remove any helpers for this proxy. this->FinalizeProxy(iter->second); // unregister the proxy. pxm->UnRegisterProxy( groupname.c_str(), iter->first.c_str(), iter->second); } } return true; } //---------------------------------------------------------------------------- bool vtkSMParaViewPipelineController::UnRegisterDependencies(vtkSMProxy* proxy) { assert(proxy != NULL); //--------------------------------------------------------------------------- // Before going any further build a list of all consumer proxies // (not pointing to internal/sub-proxies). typedef std::vector > proxyvectortype; proxyvectortype consumers; for (unsigned int cc=0, max = proxy->GetNumberOfConsumers(); cc < max; ++cc) { vtkSMProxy* consumer = proxy->GetConsumerProxy(cc); consumer = consumer? consumer->GetTrueParentProxy() : NULL; if (consumer) { consumers.push_back(consumer); } } //--------------------------------------------------------------------------- for (proxyvectortype::iterator iter = consumers.begin(), max = consumers.end(); iter != max; ++iter) { vtkSMProxy* consumer = iter->GetPointer(); if (!consumer) { continue; } if ( // Remove representations connected to this proxy, if any. consumer->IsA("vtkSMRepresentationProxy") || // Remove any animation cues for this proxy strcmp(consumer->GetXMLGroup(), "animation") == 0 || false) { this->UnRegisterProxy(consumer); } } //--------------------------------------------------------------------------- // TODO: remove any property links/proxy link setup for this proxy. return true; } //---------------------------------------------------------------------------- bool vtkSMParaViewPipelineController::UnRegisterProxy(vtkSMProxy* proxy) { if (!proxy) { return false; } SM_SCOPED_TRACE(CleanupAccessor).arg("proxy", proxy); // determine what type of proxy is this, based on that, we can finalize it. vtkSMSessionProxyManager* pxm = proxy->GetSessionProxyManager(); if (pxm->GetProxyName("sources", proxy)) { return this->UnRegisterPipelineProxy(proxy); } else if (pxm->GetProxyName("representations", proxy) || pxm->GetProxyName("scalar_bars", proxy)) { return this->UnRegisterRepresentationProxy(proxy); } else if (pxm->GetProxyName("views", proxy)) { return this->UnRegisterViewProxy(proxy); } else if (pxm->GetProxyName("animation", proxy)) { if (proxy != this->GetAnimationScene(proxy->GetSession())) { return this->UnRegisterAnimationProxy(proxy); } } else { PREPARE_FOR_UNREGISTERING(proxy); const char* known_groups[] = { "lookup_tables", "piecewise_functions", "layouts", NULL }; for (int cc=0; known_groups[cc] != NULL; ++cc) { if (const char* pname = pxm->GetProxyName(known_groups[cc], proxy)) { SM_SCOPED_TRACE(Delete).arg("proxy", proxy); // unregister dependencies. if (!this->UnRegisterDependencies(proxy)) { return false; } // this will remove both proxy-list-domain helpers and animation helpers. if (!this->FinalizeProxy(proxy)) { return false; } pxm->UnRegisterProxy(known_groups[cc], pname, proxy); return true; } } } return false; } //---------------------------------------------------------------------------- void vtkSMParaViewPipelineController::HandleLZ4Issue(vtkSMProxy* renderViewSettings) { vtkSMProperty* compressorConfig = renderViewSettings->GetProperty("CompressorConfig"); if (!compressorConfig) { return; } if (vtkPVXMLElement* hints = compressorConfig->GetHints()) { if (hints->FindNestedElementByName("SupportsLZ4") != NULL) { return; } } // We're dealing with an server that doesn't support LZ4. If the default is to // use LZ4 change it to not use LZ4. vtkSMPropertyHelper helper(compressorConfig); if (strncmp(helper.GetAsString(), "vtkLZ4Compressor", strlen("vtkLZ4Compressor")) != 0) { return; } std::string newvalue("vtkSquirtCompressor"); newvalue += helper.GetAsString() + strlen("vtkLZ4Compressor"); helper.Set(newvalue.c_str()); vtkWarningMacro( "You have connected to a server that doesn't support 'LZ4' compression for delivering " "remotely rendered images to the client. 'LZ4' is your current default " "(and recommended) compression mode. Switching to 'SQUIRT'. " "Remote rendering that uses translucent surfaces or volumes will have artifacts " "with SQUIRT. Switch to zlib or no compression to avoid those, if needed."); renderViewSettings->UpdateVTKObjects(); } //---------------------------------------------------------------------------- void vtkSMParaViewPipelineController::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); }