From 521f3d7de4453442e174949612d2c69d88ab5592 Mon Sep 17 00:00:00 2001 From: rnv Date: Tue, 11 Oct 2011 10:57:12 +0000 Subject: [PATCH] Implementation isuue "21319: EDF 1616 ALL: synchronization of 3D viewers" for the VTK viewer. --- src/SVTK/SVTK_Event.h | 2 + src/SVTK/SVTK_InteractorStyle.cxx | 4 + src/SVTK/SVTK_ViewWindow.cxx | 178 +++++++++++++++++++++++++----- src/SVTK/SVTK_ViewWindow.h | 28 ++++- 4 files changed, 182 insertions(+), 30 deletions(-) diff --git a/src/SVTK/SVTK_Event.h b/src/SVTK/SVTK_Event.h index 77e9e4875..4785d794c 100644 --- a/src/SVTK/SVTK_Event.h +++ b/src/SVTK/SVTK_Event.h @@ -73,6 +73,8 @@ namespace SVTK SetFocalPointSelected, StartFocalPointSelection, FocalPointChanged, + + OperationFinished, // rnv: invoked then SpinXY, RotateXY, DollyXY or PanXY operation is finished. LastEvent }; diff --git a/src/SVTK/SVTK_InteractorStyle.cxx b/src/SVTK/SVTK_InteractorStyle.cxx index 994b85570..5346d0981 100644 --- a/src/SVTK/SVTK_InteractorStyle.cxx +++ b/src/SVTK/SVTK_InteractorStyle.cxx @@ -271,12 +271,14 @@ void SVTK_InteractorStyle::RotateXY(int dx, int dy) GetCurrentRenderer()->ResetCameraClippingRange(); this->Render(); + this->InvokeEvent(SVTK::OperationFinished,NULL); } void SVTK_InteractorStyle::PanXY(int x, int y, int oldX, int oldY) { TranslateView(x, y, oldX, oldY); this->Render(); + this->InvokeEvent(SVTK::OperationFinished,NULL); } void SVTK_InteractorStyle::DollyXY(int dx, int dy) @@ -312,6 +314,7 @@ void SVTK_InteractorStyle::DollyXY(int dx, int dy) } this->Render(); + this->InvokeEvent(SVTK::OperationFinished,NULL); } void SVTK_InteractorStyle::SpinXY(int x, int y, int oldX, int oldY) @@ -334,6 +337,7 @@ void SVTK_InteractorStyle::SpinXY(int x, int y, int oldX, int oldY) cam->OrthogonalizeViewUp(); this->Render(); + this->InvokeEvent(SVTK::OperationFinished,NULL); } diff --git a/src/SVTK/SVTK_ViewWindow.cxx b/src/SVTK/SVTK_ViewWindow.cxx index c682aefaa..0a84e834a 100755 --- a/src/SVTK/SVTK_ViewWindow.cxx +++ b/src/SVTK/SVTK_ViewWindow.cxx @@ -46,6 +46,7 @@ #include #include #include +#include #include "QtxAction.h" @@ -123,7 +124,8 @@ SVTK_ViewWindow::SVTK_ViewWindow(SUIT_Desktop* theDesktop): SUIT_ViewWindow(theDesktop), myView(NULL), myDumpImage(QImage()), - myKeyFreeInteractorStyle(SVTK_KeyFreeInteractorStyle::New()) + myKeyFreeInteractorStyle(SVTK_KeyFreeInteractorStyle::New()), + myEventCallbackCommand(vtkCallbackCommand::New()) { setWindowFlags( windowFlags() & ~Qt::Window ); // specific of vtkSmartPointer @@ -209,6 +211,16 @@ void SVTK_ViewWindow::Initialize(SVTK_ViewModelBase* theModel) myView = new SVTK_View(this); Initialize(myView,theModel); + + + myEventCallbackCommand->SetClientData(this); + myEventCallbackCommand->SetCallback(SVTK_ViewWindow::ProcessEvents); + myEventCallbackCommand->Delete(); + + GetInteractor()->GetInteractorStyle()->AddObserver(SVTK::OperationFinished, + myEventCallbackCommand.GetPointer(), 0.0); + + myInteractor->getRenderWindow()->Render(); onResetView(); @@ -311,6 +323,7 @@ void SVTK_ViewWindow::onFrontView() { GetRenderer()->OnFrontView(); Repaint(); + emit transformed( this ); } /*! @@ -320,6 +333,7 @@ void SVTK_ViewWindow::onBackView() { GetRenderer()->OnBackView(); Repaint(); + emit transformed( this ); } /*! @@ -329,6 +343,7 @@ void SVTK_ViewWindow::onTopView() { GetRenderer()->OnTopView(); Repaint(); + emit transformed( this ); } /*! @@ -338,6 +353,7 @@ void SVTK_ViewWindow::onBottomView() { GetRenderer()->OnBottomView(); Repaint(); + emit transformed( this ); } /*! @@ -347,6 +363,7 @@ void SVTK_ViewWindow::onLeftView() { GetRenderer()->OnLeftView(); Repaint(); + emit transformed( this ); } /*! @@ -356,6 +373,7 @@ void SVTK_ViewWindow::onRightView() { GetRenderer()->OnRightView(); Repaint(); + emit transformed( this ); } /*! @@ -365,6 +383,7 @@ void SVTK_ViewWindow::onClockWiseView() { GetRenderer()->onClockWiseView(); Repaint(); + emit transformed( this ); } /*! @@ -374,6 +393,7 @@ void SVTK_ViewWindow::onAntiClockWiseView() { GetRenderer()->onAntiClockWiseView(); Repaint(); + emit transformed( this ); } /*! @@ -383,6 +403,7 @@ void SVTK_ViewWindow::onResetView() { GetRenderer()->OnResetView(); Repaint(); + emit transformed( this ); } /*! @@ -392,6 +413,7 @@ void SVTK_ViewWindow::onFitAll() { GetRenderer()->OnFitAll(); Repaint(); + emit transformed( this ); } /*! @@ -592,6 +614,7 @@ void SVTK_ViewWindow::SetScale( double theScale[3] ) { GetRenderer()->SetScale( theScale ); Repaint(); + emit transformed( this ); } /*! @@ -845,6 +868,15 @@ void SVTK_ViewWindow::onAdjustCubeAxes() GetRenderer()->OnAdjustCubeAxes(); } +void SVTK_ViewWindow::synchronize(SVTK_ViewWindow* otherViewWindow ) +{ + if ( otherViewWindow ) { + bool blocked = blockSignals( true ); + doSetVisualParameters( otherViewWindow->getVisualParameters(), true ); + blockSignals( blocked ); + } +} + /*! Emits key pressed */ @@ -1450,6 +1482,7 @@ void SVTK_ViewWindow::setVisualParameters( const QString& parameters ) */ void SVTK_ViewWindow::doSetVisualParameters( const QString& parameters, bool baseParamsOnly ) { + double pos[3], focalPnt[3], viewUp[3], parScale, scale[3]; QXmlStreamReader aReader(parameters); @@ -1517,7 +1550,8 @@ void SVTK_ViewWindow::doSetVisualParameters( const QString& parameters, bool bas camera->SetFocalPoint( focalPnt ); camera->SetViewUp( viewUp ); camera->SetParallelScale( parScale ); - SetScale( scale ); + GetRenderer()->SetScale( scale ); + //SetScale( scale ); } else { QStringList paramsLst = parameters.split( '*' ); @@ -1543,7 +1577,8 @@ void SVTK_ViewWindow::doSetVisualParameters( const QString& parameters, bool bas camera->SetFocalPoint( focalPnt ); camera->SetViewUp( viewUp ); camera->SetParallelScale( parScale ); - SetScale( scale ); + GetRenderer()->SetScale( scale ); + //SetScale( scale ); // apply graduated axes parameters if ( !baseParamsOnly ) { @@ -1572,6 +1607,7 @@ void SVTK_ViewWindow::doSetVisualParameters( const QString& parameters, bool bas } } } + Repaint(); } @@ -1870,8 +1906,9 @@ void SVTK_ViewWindow::createActions(SUIT_ResourceMgr* theResourceMgr) tr( "MNU_SYNCHRONIZE_VIEW" ), 0, this); anAction->setStatusTip(tr("DSC_SYNCHRONIZE_VIEW")); anAction->setMenu( new QMenu( this ) ); + anAction->setCheckable(true); connect(anAction->menu(), SIGNAL(aboutToShow()), this, SLOT(updateSyncViews())); - connect(anAction, SIGNAL(triggered()), this, SLOT(onSynchronizeView())); + connect(anAction, SIGNAL(triggered(bool)), this, SLOT(onSynchronizeView(bool))); mgr->registerAction( anAction, SynchronizeId ); // Switch between interaction styles @@ -2160,33 +2197,94 @@ void SVTK_ViewWindow::hideEvent( QHideEvent * theEvent ) emit Hide( theEvent ); } +void SVTK_ViewWindow::synchronizeView( SVTK_ViewWindow* viewWindow, int id ) +{ + SVTK_ViewWindow* otherViewWindow = 0; + QList compatibleViews; + + bool isSync = viewWindow->toolMgr()->action( SynchronizeId )->isChecked(); + + int vwid = viewWindow->getId(); + + SUIT_Application* app = SUIT_Session::session()->activeApplication(); + if ( !app ) return; + + QList wmlist; + app->viewManagers( viewWindow->getViewManager()->getType(), wmlist ); + + foreach( SUIT_ViewManager* wm, wmlist ) { + QVector vwlist = wm->getViews(); + + foreach( SUIT_ViewWindow* vw, vwlist ) { + SVTK_ViewWindow* vtkVW = dynamic_cast( vw ); + if ( !vtkVW ) continue; + if ( vtkVW->getId() == id ) + otherViewWindow = vtkVW; + else if ( vtkVW != viewWindow ) + compatibleViews.append( vtkVW ); + } + } + + if ( isSync && id ) { + // remove all possible disconnections + foreach( SVTK_ViewWindow* vw, compatibleViews ) { + // disconnect target view + vw->disconnect( SIGNAL( transformed( SVTK_ViewPort* ) ), viewWindow, SLOT( synchronize( SVTK_ViewPort* ) ) ); + viewWindow->disconnect( SIGNAL( transformed( SVTK_ViewPort* ) ), vw, SLOT( synchronize( SVTK_ViewPort* ) ) ); + if ( otherViewWindow ) { + // disconnect source view + vw->disconnect( SIGNAL( transformed( SVTK_ViewPort* ) ), otherViewWindow, SLOT( synchronize( SVTK_ViewPort* ) ) ); + otherViewWindow->disconnect( SIGNAL( transformed( SVTK_ViewPort* ) ), vw, SLOT( synchronize( SVTK_ViewPort* ) ) ); + } + QAction* a = vw->toolMgr()->action( SynchronizeId ); + if ( a ) { + int anid = a->data().toInt(); + if ( a->isChecked() && ( anid == id || anid == vwid ) ) { + bool blocked = a->blockSignals( true ); + a->setChecked( false ); + a->blockSignals( blocked ); + } + } + } + if ( otherViewWindow ) { + // reconnect source and target view + otherViewWindow->disconnect( SIGNAL( transformed( SVTK_ViewWindow* ) ), viewWindow, SLOT( synchronize( SVTK_ViewWindow* ) ) ); + viewWindow->disconnect( SIGNAL( transformed( SVTK_ViewWindow* ) ), otherViewWindow, SLOT( synchronize( SVTK_ViewWindow* ) ) ); + otherViewWindow->connect( viewWindow, SIGNAL( transformed( SVTK_ViewWindow* ) ), SLOT( synchronize( SVTK_ViewWindow* ) ) ); + viewWindow->connect( otherViewWindow, SIGNAL( transformed( SVTK_ViewWindow* ) ), SLOT( synchronize( SVTK_ViewWindow* ) ) ); + // synchronize target view with source view + viewWindow->doSetVisualParameters( otherViewWindow->getVisualParameters(), true ); + viewWindow->toolMgr()->action( SynchronizeId )->setData( otherViewWindow->getId() ); + otherViewWindow->toolMgr()->action( SynchronizeId )->setData( viewWindow->getId() ); + if ( !otherViewWindow->toolMgr()->action( SynchronizeId )->isChecked() ) { + bool blocked = otherViewWindow->toolMgr()->action( SynchronizeId )->blockSignals( true ); + otherViewWindow->toolMgr()->action( SynchronizeId )->setChecked( true ); + otherViewWindow->toolMgr()->action( SynchronizeId )->blockSignals( blocked ); + } + } + } + else if ( otherViewWindow ) { + // reconnect source and target view + otherViewWindow->disconnect( SIGNAL( transformed( SVTK_ViewWindow* ) ), viewWindow, SLOT( synchronize( SVTK_ViewWindow* ) ) ); + viewWindow->disconnect( SIGNAL( transformed( SVTK_ViewWindow* ) ), otherViewWindow, SLOT( synchronize( SVTK_ViewWindow* ) ) ); + viewWindow->doSetVisualParameters( otherViewWindow->getVisualParameters(), true ); + viewWindow->toolMgr()->action( SynchronizeId )->setData( otherViewWindow->getId() ); + if ( otherViewWindow->toolMgr()->action( SynchronizeId )->data().toInt() == viewWindow->getId() && otherViewWindow->toolMgr()->action( SynchronizeId )->isChecked() ) { + bool blocked = otherViewWindow->toolMgr()->action( SynchronizeId )->blockSignals( true ); + otherViewWindow->toolMgr()->action( SynchronizeId )->setChecked( false ); + otherViewWindow->toolMgr()->action( SynchronizeId )->blockSignals( blocked ); + } + } +} + /*! "Synchronize View" action slot. */ -void SVTK_ViewWindow::onSynchronizeView() +void SVTK_ViewWindow::onSynchronizeView(bool checked) { QAction* a = qobject_cast( sender() ); if ( a ) { - int id = a->data().toInt(); - if ( id != 0 ) { - SUIT_Application* app = SUIT_Session::session()->activeApplication(); - if ( !app ) return; - QList wmlist; - app->viewManagers( getViewManager()->getType(), wmlist ); - foreach( SUIT_ViewManager* wm, wmlist ) { - QVector vwlist = wm->getViews(); - foreach ( SUIT_ViewWindow* vw, vwlist ) { - SVTK_ViewWindow* vtkVW = dynamic_cast( vw ); - if ( vtkVW && vtkVW->getId() == id && vtkVW != this ) { - // perform synchronization - doSetVisualParameters( vtkVW->getVisualParameters(), true ); - } - } - } - - if ( a != toolMgr()->action( SynchronizeId ) ) - toolMgr()->action( SynchronizeId )->setData( id ); - } + synchronizeView( this, a->data().toInt() ); } } @@ -2197,6 +2295,7 @@ void SVTK_ViewWindow::updateSyncViews() { QAction* anAction = toolMgr()->action( SynchronizeId ); if ( anAction && anAction->menu() ) { + int currentId = anAction->data().toInt(); anAction->menu()->clear(); SUIT_Application* app = SUIT_Session::session()->activeApplication(); if ( app ) { @@ -2208,13 +2307,40 @@ void SVTK_ViewWindow::updateSyncViews() SVTK_ViewWindow* vtkVW = dynamic_cast( vw ); if ( !vtkVW || vtkVW == this ) continue; QAction* a = anAction->menu()->addAction( vtkVW->windowTitle() ); + if ( vtkVW->getId() == currentId ) { + QFont f = a->font(); + f.setBold( true ); + a->setFont( f ); + } a->setData( vtkVW->getId() ); - connect( a, SIGNAL( triggered() ), this, SLOT( onSynchronizeView() ) ); + connect( a, SIGNAL( triggered(bool) ), this, SLOT( onSynchronizeView(bool) ) ); } } } if ( anAction->menu()->actions().isEmpty() ) { + anAction->setData( 0 ); anAction->menu()->addAction( tr( "MNU_SYNC_NO_VIEW" ) ); } } } + + +/*! + Emit transformed signal. +*/ +void SVTK_ViewWindow::emitTransformed() { + transformed(this); +} + +/*! + Processes events +*/ +void SVTK_ViewWindow::ProcessEvents(vtkObject* vtkNotUsed(theObject), + unsigned long theEvent, + void* theClientData, + void* theCallData) +{ + SVTK_ViewWindow* self = reinterpret_cast(theClientData); + if(self) + self->emitTransformed(); +} diff --git a/src/SVTK/SVTK_ViewWindow.h b/src/SVTK/SVTK_ViewWindow.h index 5555b06d3..0e713d57a 100755 --- a/src/SVTK/SVTK_ViewWindow.h +++ b/src/SVTK/SVTK_ViewWindow.h @@ -53,6 +53,8 @@ class vtkRenderer; class vtkRenderWindow; class vtkRenderWindowInteractor; class vtkInteractorStyle; +class vtkCallbackCommand; + class SVTK_RenderWindowInteractor; class SVTK_Renderer; class SVTK_NonIsometricDlg; @@ -263,6 +265,8 @@ class SVTK_EXPORT SVTK_ViewWindow : public SUIT_ViewWindow virtual void RefreshDumpImage(); + void emitTransformed(); + //! To invoke a VTK event on #SVTK_RenderWindowInteractor instance void InvokeEvent(unsigned long theEvent, void* theCallData); @@ -310,13 +314,11 @@ public slots: void onPauseRecording(); void onStopRecording(); - void onSynchronizeView(); - void updateSyncViews(); - signals: void selectionChanged(); void actorAdded(VTKViewer_Actor*); void actorRemoved(VTKViewer_Actor*); + void transformed(SVTK_ViewWindow*); public slots: //! Redirect the request to #SVTK_Renderer::OnFrontView @@ -360,7 +362,9 @@ public slots: //! Redirect the request to #SVTK_Renderer::OnAdjustCubeAxes virtual void onAdjustCubeAxes(); - + + virtual void synchronize(SVTK_ViewWindow*); + protected slots: void onKeyPressed(QKeyEvent* event); void onKeyReleased(QKeyEvent* event); @@ -373,6 +377,12 @@ protected: virtual void Initialize(SVTK_View* theView, SVTK_ViewModelBase* theModel); + // Main process event method + static void ProcessEvents(vtkObject* object, + unsigned long event, + void* clientdata, + void* calldata); + void doSetVisualParameters( const QString&, bool = false ); void SetEventDispatcher(vtkObject* theDispatcher); @@ -407,6 +417,9 @@ protected: vtkSmartPointer myEventDispatcher; + // Used to process events + vtkSmartPointer myEventCallbackCommand; + SVTK_NonIsometricDlg* myNonIsometricDlg; SVTK_UpdateRateDlg* myUpdateRateDlg; SVTK_CubeAxesDlg* myCubeAxesDlg; @@ -427,6 +440,13 @@ protected: vtkPVAxesWidget* myAxesWidget; +private slots: + void onSynchronizeView(bool); + void updateSyncViews(); + +private: + static void synchronizeView( SVTK_ViewWindow*, int ); + private: QImage myDumpImage; }; -- 2.39.2