mirror of
https://github.com/OpenFOAM/ThirdParty-6.git
synced 2025-12-08 06:57:43 +00:00
579 lines
17 KiB
C++
579 lines
17 KiB
C++
/*=========================================================================
|
|
|
|
Program: ParaView
|
|
Module: vtkSMStateLoader.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 "vtkSMStateLoader.h"
|
|
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkPVInstantiator.h"
|
|
#include "vtkPVXMLElement.h"
|
|
#include "vtkSmartPointer.h"
|
|
#include "vtkSMProperty.h"
|
|
#include "vtkSMPropertyLink.h"
|
|
#include "vtkSMProxyIterator.h"
|
|
#include "vtkSMProxyLink.h"
|
|
#include "vtkSMProxyLocator.h"
|
|
#include "vtkSMProxyManager.h"
|
|
#include "vtkSMSession.h"
|
|
#include "vtkSMSessionProxyManager.h"
|
|
#include "vtkSMSourceProxy.h"
|
|
#include "vtkSMStateVersionController.h"
|
|
|
|
#include <map>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <assert.h>
|
|
|
|
vtkStandardNewMacro(vtkSMStateLoader);
|
|
vtkCxxSetObjectMacro(vtkSMStateLoader, ProxyLocator, vtkSMProxyLocator);
|
|
//---------------------------------------------------------------------------
|
|
struct vtkSMStateLoaderRegistrationInfo
|
|
{
|
|
std::string GroupName;
|
|
std::string ProxyName;
|
|
};
|
|
|
|
struct vtkSMStateLoaderInternals
|
|
{
|
|
bool KeepOriginalId;
|
|
typedef std::vector<vtkSMStateLoaderRegistrationInfo> VectorOfRegInfo;
|
|
typedef std::map<int, VectorOfRegInfo> RegInfoMapType;
|
|
RegInfoMapType RegistrationInformation;
|
|
std::vector<vtkTypeUInt32> AlignedMappingIdTable;
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
vtkSMStateLoader::vtkSMStateLoader()
|
|
{
|
|
this->Internal = new vtkSMStateLoaderInternals;
|
|
this->ServerManagerStateElement = 0;
|
|
this->KeepIdMapping = 0;
|
|
this->ProxyLocator = vtkSMProxyLocator::New();
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
vtkSMStateLoader::~vtkSMStateLoader()
|
|
{
|
|
this->SetProxyLocator(0);
|
|
this->ServerManagerStateElement = 0;
|
|
this->ProxyLocator = 0;
|
|
delete this->Internal;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
vtkSMProxy* vtkSMStateLoader::LocateExistingProxyUsingRegistrationName(
|
|
vtkTypeUInt32 id)
|
|
{
|
|
vtkSMStateLoaderInternals::RegInfoMapType::iterator iter
|
|
= this->Internal->RegistrationInformation.find(id);
|
|
if (iter == this->Internal->RegistrationInformation.end())
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
vtkSMSessionProxyManager* pxm = this->GetSessionProxyManager();
|
|
assert(pxm != NULL);
|
|
|
|
vtkSMStateLoaderInternals::VectorOfRegInfo::iterator iter2;
|
|
for (iter2 =iter->second.begin(); iter2 != iter->second.end(); iter2++)
|
|
{
|
|
vtkSMProxy* proxy = pxm->GetProxy(iter2->GroupName.c_str(),
|
|
iter2->ProxyName.c_str());
|
|
if (proxy)
|
|
{
|
|
return proxy;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
vtkSMProxy* vtkSMStateLoader::CreateProxy( const char* xml_group,
|
|
const char* xml_name,
|
|
const char* subProxyName)
|
|
{
|
|
vtkSMSessionProxyManager* pxm = this->GetSessionProxyManager();
|
|
assert (pxm != NULL);
|
|
|
|
//**************************************************************************
|
|
// This is temporary code until we clean up time-keeper and animation scene
|
|
// interactions. There needs to be some rework with the management of
|
|
// time-keeper, making it a SM-behavior perhaps. Until that happens, I am
|
|
// letting this piece of code be which ensures that there's only open
|
|
// time-keeper and animation scene in the application.
|
|
if (xml_group && xml_name && strcmp(xml_group, "animation")==0
|
|
&& strcmp(xml_name, "AnimationScene")==0)
|
|
{
|
|
// If an animation scene already exists, we use that.
|
|
vtkSMProxy* scene = pxm->FindProxy("animation", "animation", "AnimationScene");
|
|
if (scene)
|
|
{
|
|
scene->Register(this);
|
|
return scene;
|
|
}
|
|
}
|
|
else if (xml_group && xml_name && strcmp(xml_group, "animation")==0
|
|
&& strcmp(xml_name, "TimeAnimationCue")==0)
|
|
{
|
|
// If an animation cue already exists, we use that.
|
|
vtkSMProxy* cue = pxm->FindProxy("animation", "animation", "TimeAnimationCue");
|
|
if (cue)
|
|
{
|
|
cue->Register(this);
|
|
return cue;
|
|
}
|
|
}
|
|
else if (xml_group && xml_name && strcmp(xml_group, "misc") == 0
|
|
&& strcmp(xml_name, "TimeKeeper") == 0)
|
|
{
|
|
// There is only one time keeper per connection, simply
|
|
// load the state on the timekeeper.
|
|
vtkSMProxy* timekeeper = pxm->FindProxy("timekeeper", xml_group, xml_name);
|
|
if (timekeeper)
|
|
{
|
|
timekeeper->Register(this);
|
|
return timekeeper;
|
|
}
|
|
}
|
|
//**************************************************************************
|
|
|
|
// If all else fails, let the superclass handle it:
|
|
return this->Superclass::CreateProxy(xml_group, xml_name, subProxyName);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void vtkSMStateLoader::CreatedNewProxy(vtkTypeUInt32 id, vtkSMProxy* proxy)
|
|
{
|
|
// Ensure that the proxy is created before it is registered, unless we are
|
|
// reviving the server-side server manager, which needs special handling.
|
|
if(this->Internal->KeepOriginalId)
|
|
{
|
|
proxy->SetGlobalID(id);
|
|
}
|
|
|
|
|
|
proxy->UpdateVTKObjects();
|
|
if (proxy->IsA("vtkSMSourceProxy"))
|
|
{
|
|
vtkSMSourceProxy::SafeDownCast(proxy)->UpdatePipelineInformation();
|
|
}
|
|
this->RegisterProxy(id, proxy);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void vtkSMStateLoader::RegisterProxy(vtkTypeUInt32 id, vtkSMProxy* proxy)
|
|
{
|
|
vtkSMStateLoaderInternals::RegInfoMapType::iterator iter
|
|
= this->Internal->RegistrationInformation.find(id);
|
|
if (iter == this->Internal->RegistrationInformation.end())
|
|
{
|
|
return;
|
|
}
|
|
vtkSMStateLoaderInternals::VectorOfRegInfo::iterator iter2;
|
|
for (iter2 =iter->second.begin(); iter2 != iter->second.end(); iter2++)
|
|
{
|
|
this->RegisterProxyInternal(iter2->GroupName.c_str(),
|
|
iter2->ProxyName.c_str(), proxy);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void vtkSMStateLoader::RegisterProxyInternal(const char* group,
|
|
const char* name, vtkSMProxy* proxy)
|
|
{
|
|
vtkSMSessionProxyManager* pxm = this->GetSessionProxyManager();
|
|
assert(pxm != NULL);
|
|
|
|
if (pxm->GetProxyName(group, proxy))
|
|
{
|
|
// Don't re-register a proxy in the same group.
|
|
return;
|
|
}
|
|
pxm->RegisterProxy(group, name, proxy);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
vtkPVXMLElement* vtkSMStateLoader::LocateProxyElement(vtkTypeUInt32 id)
|
|
{
|
|
return this->LocateProxyElementInternal(
|
|
this->ServerManagerStateElement, id);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
vtkPVXMLElement* vtkSMStateLoader::LocateProxyElementInternal(
|
|
vtkPVXMLElement* root, vtkTypeUInt32 id_)
|
|
{
|
|
if (!root)
|
|
{
|
|
vtkErrorMacro("No root is defined. Cannot locate proxy element with id "
|
|
<< id_);
|
|
return 0;
|
|
}
|
|
vtkIdType id = static_cast<vtkIdType>(id_);
|
|
|
|
unsigned int numElems = root->GetNumberOfNestedElements();
|
|
unsigned int i=0;
|
|
for (i=0; i<numElems; i++)
|
|
{
|
|
vtkPVXMLElement* currentElement = root->GetNestedElement(i);
|
|
if (currentElement->GetName() &&
|
|
strcmp(currentElement->GetName(), "Proxy") == 0)
|
|
{
|
|
vtkIdType currentId;
|
|
if (!currentElement->GetScalarAttribute("id", ¤tId))
|
|
{
|
|
continue;
|
|
}
|
|
if (id != currentId)
|
|
{
|
|
continue;
|
|
}
|
|
return currentElement;
|
|
}
|
|
}
|
|
|
|
// If proxy was not found on root level, go into nested elements
|
|
for (i=0; i<numElems; i++)
|
|
{
|
|
vtkPVXMLElement* currentElement = root->GetNestedElement(i);
|
|
vtkPVXMLElement* res = this->LocateProxyElementInternal(currentElement, id);
|
|
if (res)
|
|
{
|
|
return res;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
int vtkSMStateLoader::BuildProxyCollectionInformation(
|
|
vtkPVXMLElement* collectionElement)
|
|
{
|
|
const char* groupName = collectionElement->GetAttribute("name");
|
|
if (!groupName)
|
|
{
|
|
vtkErrorMacro("Required attribute name is missing.");
|
|
return 0;
|
|
}
|
|
unsigned int numElems = collectionElement->GetNumberOfNestedElements();
|
|
for (unsigned int i=0; i<numElems; i++)
|
|
{
|
|
vtkPVXMLElement* currentElement = collectionElement->GetNestedElement(i);
|
|
if (currentElement->GetName() &&
|
|
strcmp(currentElement->GetName(), "Item") == 0)
|
|
{
|
|
int id;
|
|
if (!currentElement->GetScalarAttribute("id", &id))
|
|
{
|
|
vtkErrorMacro("Could not read id for Item. Skipping.");
|
|
continue;
|
|
}
|
|
const char* name = currentElement->GetAttribute("name");
|
|
if (!name)
|
|
{
|
|
vtkErrorMacro("Attribute: name is missing. Cannot register proxy "
|
|
"with the proxy manager.");
|
|
continue;
|
|
}
|
|
vtkSMStateLoaderRegistrationInfo info;
|
|
info.GroupName = groupName;
|
|
info.ProxyName = name;
|
|
this->Internal->RegistrationInformation[id].push_back(info);
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
int vtkSMStateLoader::HandleProxyCollection(vtkPVXMLElement* collectionElement)
|
|
{
|
|
const char* groupName = collectionElement->GetAttribute("name");
|
|
if (!groupName)
|
|
{
|
|
vtkErrorMacro("Requied attribute name is missing.");
|
|
return 0;
|
|
}
|
|
unsigned int numElems = collectionElement->GetNumberOfNestedElements();
|
|
for (unsigned int i=0; i<numElems; i++)
|
|
{
|
|
vtkPVXMLElement* currentElement = collectionElement->GetNestedElement(i);
|
|
if (currentElement->GetName() &&
|
|
strcmp(currentElement->GetName(), "Item") == 0)
|
|
{
|
|
int id;
|
|
if (!currentElement->GetScalarAttribute("id", &id))
|
|
{
|
|
vtkErrorMacro("Could not read id for Item. Skipping.");
|
|
continue;
|
|
}
|
|
|
|
vtkSMProxy* proxy = this->ProxyLocator->LocateProxy(id);
|
|
if (!proxy)
|
|
{
|
|
continue;
|
|
}
|
|
const char* name = currentElement->GetAttribute("name");
|
|
if (!name)
|
|
{
|
|
vtkErrorMacro("Attribute: name is missing. Cannot register proxy "
|
|
"with the proxy manager.");
|
|
proxy->Delete();
|
|
continue;
|
|
}
|
|
// No need to register
|
|
//pm->RegisterProxy(groupName, name, proxy);
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void vtkSMStateLoader::HandleCustomProxyDefinitions(
|
|
vtkPVXMLElement* element)
|
|
{
|
|
vtkSMSessionProxyManager* pm = this->GetSessionProxyManager();
|
|
assert(pm != NULL);
|
|
pm->LoadCustomProxyDefinitions(element);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
int vtkSMStateLoader::HandleLinks(vtkPVXMLElement* element)
|
|
{
|
|
vtkSMSessionProxyManager* pxm = this->GetSessionProxyManager();
|
|
assert(pxm != NULL);
|
|
|
|
unsigned int numElems = element->GetNumberOfNestedElements();
|
|
for (unsigned int cc=0; cc < numElems; cc++)
|
|
{
|
|
vtkPVXMLElement* currentElement= element->GetNestedElement(cc);
|
|
const char* name = currentElement->GetName();
|
|
const char* linkname = currentElement->GetAttribute("name");
|
|
|
|
if (name && linkname)
|
|
{
|
|
vtkSMLink* link = pxm->GetRegisteredLink(linkname);
|
|
if (link == NULL)
|
|
{
|
|
std::string classname = "vtkSM";
|
|
classname += name;
|
|
vtkSmartPointer<vtkObject> obj;
|
|
obj.TakeReference(vtkPVInstantiator::CreateInstance(classname.c_str()));
|
|
link = vtkSMLink::SafeDownCast(obj);
|
|
if (link == NULL)
|
|
{
|
|
vtkWarningMacro("Failed to create object for link (name="
|
|
<< name
|
|
<< "). Expected type was " << classname.c_str()
|
|
<< ". Skipping.");
|
|
continue;
|
|
}
|
|
pxm->RegisterLink(linkname, link);
|
|
}
|
|
assert(link != NULL);
|
|
if (!link->LoadXMLState(currentElement, this->ProxyLocator))
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Load the global_properties
|
|
if (vtkSMProxy* globalPropertiesProxy = pxm->GetProxy("global_properties", "ColorPalette"))
|
|
{
|
|
globalPropertiesProxy->LoadXMLState(element, this->ProxyLocator);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
bool vtkSMStateLoader::VerifyXMLVersion(vtkPVXMLElement* rootElement)
|
|
{
|
|
const char* version = rootElement->GetAttribute("version");
|
|
if (!version)
|
|
{
|
|
vtkWarningMacro("ServerManagerState missing \"version\" information.");
|
|
return true;
|
|
}
|
|
|
|
// Nothing to check here really.
|
|
return true;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
int vtkSMStateLoader::LoadState(vtkPVXMLElement* elem, bool keepOriginalId)
|
|
{
|
|
this->Internal->KeepOriginalId = keepOriginalId;
|
|
if (!elem)
|
|
{
|
|
vtkErrorMacro("Cannot load state from (null) root element.");
|
|
return 0;
|
|
}
|
|
|
|
vtkSMSessionProxyManager* pxm = this->GetSessionProxyManager();
|
|
if (pxm == NULL)
|
|
{
|
|
vtkErrorMacro("Cannot load state without a ProxyManager");
|
|
return 0;
|
|
}
|
|
|
|
if (!this->ProxyLocator)
|
|
{
|
|
vtkErrorMacro("Please set the locator correctly.");
|
|
return 0;
|
|
}
|
|
|
|
this->ProxyLocator->SetDeserializer(this);
|
|
int ret = this->LoadStateInternal(elem);
|
|
this->ProxyLocator->SetDeserializer(0);
|
|
|
|
// BUG #10650. When animation scene time ranges are read from the state, they
|
|
// often override those that the timekeeper painstakingly computed. Here we
|
|
// explicitly trigger the timekeeper so that the scene re-determines the
|
|
// ranges, unless they are locked of course.
|
|
vtkSMProxy* timekeeper = pxm->GetProxy("timekeeper", "TimeKeeper");
|
|
if (timekeeper)
|
|
{
|
|
timekeeper->GetProperty("TimeRange")->Modified();
|
|
timekeeper->GetProperty("TimestepValues")->Modified();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
int vtkSMStateLoader::LoadStateInternal(vtkPVXMLElement* parent)
|
|
{
|
|
vtkPVXMLElement* rootElement = parent;
|
|
if (rootElement->GetName() &&
|
|
strcmp(rootElement->GetName(),"ServerManagerState") != 0)
|
|
{
|
|
rootElement = rootElement->FindNestedElementByName("ServerManagerState");
|
|
if (!rootElement)
|
|
{
|
|
vtkErrorMacro("Failed to locate <ServerManagerState /> element."
|
|
<< "Cannot load server manager state.");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
vtkSMStateVersionController* convertor = vtkSMStateVersionController::New();
|
|
if (!convertor->Process(parent))
|
|
{
|
|
vtkWarningMacro("State convertor was not able to convert the state to current "
|
|
"version successfully");
|
|
}
|
|
convertor->Delete();
|
|
|
|
if (!this->VerifyXMLVersion(rootElement))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
this->ServerManagerStateElement = rootElement;
|
|
|
|
unsigned int numElems = rootElement->GetNumberOfNestedElements();
|
|
unsigned int i;
|
|
for (i=0; i<numElems; i++)
|
|
{
|
|
vtkPVXMLElement* currentElement = rootElement->GetNestedElement(i);
|
|
const char* name = currentElement->GetName();
|
|
if (name)
|
|
{
|
|
if (strcmp(name, "ProxyCollection") == 0)
|
|
{
|
|
if (!this->BuildProxyCollectionInformation(currentElement))
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Load all compound proxy definitions.
|
|
for (i=0; i<numElems; i++)
|
|
{
|
|
vtkPVXMLElement* currentElement = rootElement->GetNestedElement(i);
|
|
const char* name = currentElement->GetName();
|
|
if (name)
|
|
{
|
|
if (strcmp(name, "CustomProxyDefinitions") == 0)
|
|
{
|
|
this->HandleCustomProxyDefinitions(currentElement);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i=0; i<numElems; i++)
|
|
{
|
|
vtkPVXMLElement* currentElement = rootElement->GetNestedElement(i);
|
|
const char* name = currentElement->GetName();
|
|
if (name)
|
|
{
|
|
if (strcmp(name, "ProxyCollection") == 0)
|
|
{
|
|
if (!this->HandleProxyCollection(currentElement))
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
else if (strcmp(name, "Links") == 0)
|
|
{
|
|
this->HandleLinks(currentElement);
|
|
}
|
|
}
|
|
}
|
|
|
|
// If KeepIdMapping
|
|
this->Internal->AlignedMappingIdTable.clear();
|
|
if(this->KeepIdMapping != 0)
|
|
{
|
|
vtkSMStateLoaderInternals::RegInfoMapType::iterator iter =
|
|
this->Internal->RegistrationInformation.begin();
|
|
while(iter != this->Internal->RegistrationInformation.end())
|
|
{
|
|
vtkSMProxy* proxy =
|
|
this->LocateExistingProxyUsingRegistrationName(iter->first);
|
|
if(proxy)
|
|
{
|
|
this->Internal->AlignedMappingIdTable.push_back(iter->first);
|
|
this->Internal->AlignedMappingIdTable.push_back(proxy->GetGlobalID());
|
|
}
|
|
// Move forward
|
|
iter++;
|
|
}
|
|
}
|
|
|
|
// Clear internal data structures.
|
|
this->Internal->RegistrationInformation.clear();
|
|
this->ServerManagerStateElement = 0;
|
|
return 1;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void vtkSMStateLoader::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os, indent);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
vtkTypeUInt32* vtkSMStateLoader::GetMappingArray(int &size)
|
|
{
|
|
size = static_cast<int>(this->Internal->AlignedMappingIdTable.size());
|
|
return &this->Internal->AlignedMappingIdTable[0];
|
|
}
|