diff --git a/Documentation/release/dev/add-frame-options-extracts.md b/Documentation/release/dev/add-frame-options-extracts.md new file mode 100644 index 0000000000000000000000000000000000000000..3b40e81f7660a025e2759f9f7cdb4efa49466f4f --- /dev/null +++ b/Documentation/release/dev/add-frame-options-extracts.md @@ -0,0 +1,4 @@ +## Add Frame Parameters for Save Extracts + +`Save Extracts` now has `FrameWindow` and `FrameStride` parameters which allow you +to limit the frame timesteps window and select a stride for it. diff --git a/Qt/ApplicationComponents/pqSaveExtractsReaction.cxx b/Qt/ApplicationComponents/pqSaveExtractsReaction.cxx index 7909b6126c5c798a9eb0a74419fa16adda76a9ee..1c53c78b3202745510aa069d610be50cd67c3dcc 100644 --- a/Qt/ApplicationComponents/pqSaveExtractsReaction.cxx +++ b/Qt/ApplicationComponents/pqSaveExtractsReaction.cxx @@ -37,8 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "pqCoreUtilities.h" #include "pqProgressManager.h" #include "pqProxyWidgetDialog.h" + #include "vtkNew.h" #include "vtkSMParaViewPipelineController.h" +#include "vtkSMPropertyHelper.h" #include "vtkSMSaveAnimationExtractsProxy.h" #include "vtkSMSessionProxyManager.h" #include "vtkSmartPointer.h" @@ -62,6 +64,8 @@ bool pqSaveExtractsReaction::generateExtracts() if (exporter) { controller->PreInitializeProxy(exporter); + auto scene = controller->FindAnimationScene(pxm->GetSession()); + vtkSMPropertyHelper(exporter, "AnimationScene").Set(scene); controller->PostInitializeProxy(exporter); pqProxyWidgetDialog dialog(exporter, pqCoreUtilities::mainWidget()); @@ -72,7 +76,7 @@ bool pqSaveExtractsReaction::generateExtracts() pqAnimationProgressDialog progress( "Save Extracts Progress", "Abort", 0, 100, pqCoreUtilities::mainWidget()); progress.setWindowTitle("Saving Extracts ..."); - progress.setAnimationScene(controller->FindAnimationScene(pxm->GetSession())); + progress.setAnimationScene(scene); progress.show(); auto appcore = pqApplicationCore::instance(); diff --git a/Remoting/Animation/Resources/animation.xml b/Remoting/Animation/Resources/animation.xml index ce2195a74e4b3dbab2f5dd25b7c3f0c6b3215b9a..8ce3e87dfbc16c4e56a207b6952bf445b2765d7b 100644 --- a/Remoting/Animation/Resources/animation.xml +++ b/Remoting/Animation/Resources/animation.xml @@ -717,9 +717,50 @@ - - - + + + + + + + Frame rate in frames-per-second (FPS). + + + + + + + The stride which is used to extract the next frame. + E.g. 1, 2, 3, would have frame stride = 1, while 1, 3, 5 would have frame stride = 2. + + + + + + + + + + + + Specify a window to save only a part of the animation. + + + + + + + + diff --git a/Remoting/Animation/vtkSMSaveAnimationExtractsProxy.cxx b/Remoting/Animation/vtkSMSaveAnimationExtractsProxy.cxx index ffe9c35b7505b598ca15cc0c753b4cc668d79e4c..adbab52695083d8b4aa2fd1ae016e67d82882771 100644 --- a/Remoting/Animation/vtkSMSaveAnimationExtractsProxy.cxx +++ b/Remoting/Animation/vtkSMSaveAnimationExtractsProxy.cxx @@ -14,6 +14,7 @@ =========================================================================*/ #include "vtkSMSaveAnimationExtractsProxy.h" +#include "vtkCompositeAnimationPlayer.h" #include "vtkNew.h" #include "vtkObjectFactory.h" #include "vtkPVProgressHandler.h" @@ -105,8 +106,7 @@ bool vtkSMSaveAnimationExtractsProxy::SaveExtracts() { auto session = this->GetSession(); - vtkNew controller; - auto scene = controller->FindAnimationScene(session); + vtkSMProxy* scene = vtkSMPropertyHelper(this, "AnimationScene").GetAsProxy(); if (!scene) { vtkErrorMacro("No animation scene found. Cannot generate extracts."); @@ -120,6 +120,48 @@ bool vtkSMSaveAnimationExtractsProxy::SaveExtracts() vtkNew writer; writer->Initialize(this); writer->SetAnimationScene(scene); + writer->SetStride(vtkSMPropertyHelper(this, "FrameStride").GetAsInt()); + // Convert frame window to PlaybackTimeWindow; FrameWindow is an integral + // value indicating the frame number of timestep; PlaybackTimeWindow is double + // values as animation time. + int frameWindow[2] = { 0, 0 }; + vtkSMPropertyHelper(this, "FrameWindow").Get(frameWindow, 2); + double playbackTimeWindow[2] = { -1, 0 }; + switch (vtkSMPropertyHelper(scene, "PlayMode").GetAsInt()) + { + case vtkCompositeAnimationPlayer::SEQUENCE: + { + int numFrames = vtkSMPropertyHelper(scene, "NumberOfFrames").GetAsInt(); + double startTime = vtkSMPropertyHelper(scene, "StartTime").GetAsDouble(); + double endTime = vtkSMPropertyHelper(scene, "EndTime").GetAsDouble(); + frameWindow[0] = frameWindow[0] < 0 ? 0 : frameWindow[0]; + frameWindow[1] = frameWindow[1] >= numFrames ? numFrames - 1 : frameWindow[1]; + playbackTimeWindow[0] = + startTime + ((endTime - startTime) * frameWindow[0]) / (numFrames - 1); + playbackTimeWindow[1] = + startTime + ((endTime - startTime) * frameWindow[1]) / (numFrames - 1); + } + break; + case vtkCompositeAnimationPlayer::SNAP_TO_TIMESTEPS: + { + vtkSMProxy* timeKeeper = vtkSMPropertyHelper(scene, "TimeKeeper").GetAsProxy(); + vtkSMPropertyHelper tsValuesHelper(timeKeeper, "TimestepValues"); + int numTS = tsValuesHelper.GetNumberOfElements(); + frameWindow[0] = frameWindow[0] < 0 ? 0 : frameWindow[0]; + frameWindow[1] = frameWindow[1] >= numTS ? numTS - 1 : frameWindow[1]; + playbackTimeWindow[0] = tsValuesHelper.GetAsDouble(frameWindow[0]); + playbackTimeWindow[1] = tsValuesHelper.GetAsDouble(frameWindow[1]); + } + + break; + case vtkCompositeAnimationPlayer::REAL_TIME: + // this should not happen. vtkSMSaveAnimationProxy::Prepare() should have + // changed the play mode to SEQUENCE or SNAP_TO_TIMESTEPS. + abort(); + } + writer->SetStartFileCount(frameWindow[0]); + writer->SetPlaybackTimeWindow(playbackTimeWindow); + // register with progress handler so we monitor progress events. session->GetProgressHandler()->RegisterProgressEvent( writer.Get(), static_cast(this->GetGlobalID())); diff --git a/Remoting/Animation/vtkSMSaveAnimationProxy.cxx b/Remoting/Animation/vtkSMSaveAnimationProxy.cxx index 7d5d93c8dda755520b767982bbdaaad7b96d3e8a..145b3f6654fcb7ebe92e2dce0b5aff6324bb9b72 100644 --- a/Remoting/Animation/vtkSMSaveAnimationProxy.cxx +++ b/Remoting/Animation/vtkSMSaveAnimationProxy.cxx @@ -23,13 +23,11 @@ #include "vtkNew.h" #include "vtkObjectFactory.h" #include "vtkPVProgressHandler.h" -#include "vtkPVRenderingCapabilitiesInformation.h" #include "vtkPVServerInformation.h" #include "vtkPVXMLElement.h" #include "vtkRenderWindow.h" #include "vtkSMAnimationScene.h" #include "vtkSMAnimationSceneWriter.h" -#include "vtkSMParaViewPipelineController.h" #include "vtkSMProperty.h" #include "vtkSMPropertyHelper.h" #include "vtkSMProxyIterator.h" diff --git a/Wrapping/Python/paraview/simple.py b/Wrapping/Python/paraview/simple.py index a09fb6ec4b5560c4bc87d60db2a16172bd5d0a39..9955b3144501b736f3250d63c4210560bb2a7651 100644 --- a/Wrapping/Python/paraview/simple.py +++ b/Wrapping/Python/paraview/simple.py @@ -565,8 +565,11 @@ def SaveExtracts(**kwargs): scene.UpdateAnimationUsingDataTimeSteps() - pxm = servermanager.ProxyManager() - proxy = servermanager._getPyProxy(pxm.NewProxy("misc", "SaveAnimationExtracts")) + controller = servermanager.ParaViewPipelineController() + proxy = servermanager.misc.SaveAnimationExtracts() + controller.PreInitializeProxy(proxy) + proxy.AnimationScene = scene + controller.PostInitializeProxy(proxy) SetProperties(proxy, **kwargs) return proxy.SaveExtracts()