Files
ThirdParty-6/ParaView-5.0.1/ParaViewCore/Animation/vtkPVServerSideAnimationPlayer.cxx

245 lines
7.8 KiB
C++

/*=========================================================================
Program: ParaView
Module: vtkPVServerSideAnimationPlayer.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 "vtkPVServerSideAnimationPlayer.h"
#include "vtkCommand.h"
#include "vtkMultiProcessController.h"
#include "vtkNetworkAccessManager.h"
#include "vtkNew.h"
#include "vtkObjectFactory.h"
#include "vtkPVXMLElement.h"
#include "vtkPVXMLParser.h"
#include "vtkProcessModule.h"
#include "vtkSMAnimationScene.h"
#include "vtkSMAnimationSceneImageWriter.h"
#include "vtkSMPropertyHelper.h"
#include "vtkSMProxy.h"
#include "vtkSMProxyDefinitionManager.h"
#include "vtkSMProxyIterator.h"
#include "vtkSMRenderViewProxy.h"
#include "vtkSMSession.h"
#include "vtkSMSessionProxyManager.h"
#include "vtkSmartPointer.h"
#include "vtkWeakPointer.h"
#include <assert.h>
#include <string>
#include <sstream>
//****************************************************************************
class vtkPVServerSideAnimationPlayer::vtkInternals
{
public:
vtkInternals(vtkPVServerSideAnimationPlayer* parent)
: ObserverId(0),
WatchSessionID(0)
{
this->Owner = parent;
vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
if (!pm)
{
return;
}
if (pm->GetPartitionId() == 0)
{
// Root node
// Grab SessionServer and attach the session core to our vtkObject which
// is a SMSession.
vtkPVSessionBase* serverSession =
vtkPVSessionBase::SafeDownCast(pm->GetActiveSession());
this->WatchSessionID = pm->GetSessionID(serverSession);
assert("Server session were find" && serverSession);
this->Session.TakeReference(vtkSMSession::New(serverSession));
// Make sure the proxy definition manager will use the proper session core
// Only for Root node, satelites don't have SessionProxyManager
if(this->Session->GetSessionProxyManager())
{
vtkSMProxyDefinitionManager* definitionManager =
this->Session->GetSessionProxyManager()->GetProxyDefinitionManager();
definitionManager->SetSession(NULL); // This will force the session to be properly set later on
definitionManager->SetSession(this->Session.GetPointer());
// Attach to unregister event, so that when the "active" session is unregistered, we can
// do the cleanup.
this->ObserverId = pm->AddObserver(vtkCommand::ConnectionClosedEvent,
this, &vtkPVServerSideAnimationPlayer::vtkInternals::OnUnRegisterSession);
}
}
else
{
// Satellite
vtkProcessModule::GetProcessModule()->UpdateProcessType(vtkProcessModule::PROCESS_BATCH, false);
}
}
~vtkInternals()
{
if(this->ObserverId != 0)
{
vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
pm->RemoveObserver(this->ObserverId);
this->ObserverId = 0;
}
}
public:
vtkWeakPointer<vtkPVServerSideAnimationPlayer> Owner;
vtkSmartPointer<vtkSMSession> Session;
vtkSmartPointer<vtkSMAnimationSceneImageWriter> Writer;
vtkSmartPointer<vtkPVXMLElement> XMLState;
private:
unsigned long ObserverId;
vtkIdType WatchSessionID;
void OnUnRegisterSession(vtkObject* caller, unsigned long eventid, void* calldata)
{
assert(vtkProcessModule::SafeDownCast(caller) != NULL &&
eventid == vtkCommand::ConnectionClosedEvent);
(void)caller;
(void)eventid;
vtkIdType sessionId = *(reinterpret_cast<vtkIdType*>(calldata));
if (sessionId <= 0 || sessionId != this->WatchSessionID)
{
return;
}
caller->RemoveObserver(this->ObserverId);
this->ObserverId = 0;
this->WatchSessionID = 0;
if (this->Owner)
{
this->Owner->TriggerExecution();
}
}
};
//****************************************************************************
vtkStandardNewMacro(vtkPVServerSideAnimationPlayer);
//----------------------------------------------------------------------------
vtkPVServerSideAnimationPlayer::vtkPVServerSideAnimationPlayer()
{
this->Internals = new vtkInternals(this);
}
//----------------------------------------------------------------------------
vtkPVServerSideAnimationPlayer::~vtkPVServerSideAnimationPlayer()
{
delete this->Internals;
this->Internals = 0;
}
//----------------------------------------------------------------------------
void vtkPVServerSideAnimationPlayer::SetWriter(vtkSMAnimationSceneImageWriter* writer)
{
this->Internals->Writer = writer;
}
//----------------------------------------------------------------------------
void vtkPVServerSideAnimationPlayer::SetSessionProxyManagerState(const char* xml_state_content)
{
if(xml_state_content == NULL || strlen(xml_state_content) == 0)
{
this->Internals->XMLState = NULL;
}
else
{
vtkNew<vtkPVXMLParser> parser;
parser->Parse(xml_state_content);
this->Internals->XMLState = parser->GetRootElement();
}
}
//----------------------------------------------------------------------------
void vtkPVServerSideAnimationPlayer::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
//----------------------------------------------------------------------------
void vtkPVServerSideAnimationPlayer::TriggerExecution()
{
// Ensure only one execution
if(this->Internals->Session)
{
// Switch process type to Batch mode
vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
vtkProcessModule::GetProcessModule()->UpdateProcessType(vtkProcessModule::PROCESS_BATCH, false);
// Make sure our internal session will be used across rendering calls and
// proxy management
vtkIdType tmpSessionID = pm->RegisterSession(this->Internals->Session);
this->Internals->Session->Activate();
// Update our local SessionProxyManager state
vtkSMSessionProxyManager* spxm = this->Internals->Session->GetSessionProxyManager();
spxm->LoadXMLState(this->Internals->XMLState, NULL, true);
vtkNew<vtkSMProxyIterator> proxyIter;
proxyIter->SetSession(this->Internals->Session);
// Mark all views so that they render offscreen.
// BUG #10159.
for (proxyIter->Begin(); !proxyIter->IsAtEnd(); proxyIter->Next())
{
vtkSMViewProxy* view = vtkSMViewProxy::SafeDownCast(proxyIter->GetProxy());
// We need to ensure that we skip prototypes.
if (view && !view->IsPrototype())
{
if (vtkSMPropertyHelper(view,
"UseOffscreenRenderingForScreenshots", true).GetAsInt() == 1)
{
vtkSMPropertyHelper(view, "UseOffscreenRendering", true).Set(1);
view->UpdateVTKObjects();
}
}
}
// Write any animations.
for (proxyIter->Begin(); !proxyIter->IsAtEnd(); proxyIter->Next())
{
vtkSMAnimationScene* scene =
vtkSMAnimationScene::SafeDownCast(
proxyIter->GetProxy()->GetClientSideObject());
if (scene)
{
if (!this->Internals->Writer)
{
scene->Play();
}
else
{
this->Internals->Writer->SetAnimationScene(scene);
if (!this->Internals->Writer->Save())
{
vtkErrorMacro("Failed to save animation.");
}
break;
}
}
}
// Disconnect our session from process module
this->Internals->Session->DeActivate();
pm->UnRegisterSession(tmpSessionID);
this->Internals->Session->GetSessionProxyManager()->UnRegisterProxies();
}
// Clean up memory
this->Internals->Session = NULL;
}