From ebe38156f99322f96cfe86347908c7a55f340afe Mon Sep 17 00:00:00 2001 From: mbs Date: Tue, 4 Jul 2023 18:15:27 +0100 Subject: [PATCH] initial implementation of automatic rotation in SHAPER's OCC viewer --- src/OCCViewer/CMakeLists.txt | 2 + src/OCCViewer/OCCViewer_AutoRotate.cxx | 125 +++++++++++++++++++++++ src/OCCViewer/OCCViewer_AutoRotate.h | 45 +++++++++ src/OCCViewer/OCCViewer_ViewManager.cxx | 26 +++++ src/OCCViewer/OCCViewer_ViewManager.h | 4 + src/OCCViewer/OCCViewer_ViewPort3d.cxx | 129 +++++++++++++++++++++--- src/OCCViewer/OCCViewer_ViewPort3d.h | 15 +++ src/OCCViewer/OCCViewer_ViewWindow.cxx | 25 +++++ src/OCCViewer/OCCViewer_ViewWindow.h | 17 +++- src/SUIT/CMakeLists.txt | 2 + src/SUIT/SUIT_AutoRotate.cxx | 121 ++++++++++++++++++++++ src/SUIT/SUIT_AutoRotate.h | 67 ++++++++++++ src/SUIT/SUIT_ViewWindow.cxx | 13 +++ src/SUIT/SUIT_ViewWindow.h | 9 +- 14 files changed, 582 insertions(+), 18 deletions(-) create mode 100644 src/OCCViewer/OCCViewer_AutoRotate.cxx create mode 100644 src/OCCViewer/OCCViewer_AutoRotate.h create mode 100644 src/SUIT/SUIT_AutoRotate.cxx create mode 100644 src/SUIT/SUIT_AutoRotate.h diff --git a/src/OCCViewer/CMakeLists.txt b/src/OCCViewer/CMakeLists.txt index d151df33b..499577b5c 100644 --- a/src/OCCViewer/CMakeLists.txt +++ b/src/OCCViewer/CMakeLists.txt @@ -56,6 +56,7 @@ SET(_link_LIBRARIES # header files / to be processed by moc SET(_moc_HEADERS OCCViewer_AISSelector.h + OCCViewer_AutoRotate.h OCCViewer_AxialScaleDlg.h OCCViewer_ClippingDlg.h OCCViewer_RayTracingDlg.h @@ -167,6 +168,7 @@ QT_ADD_RESOURCES(_rcc_SOURCES ${_rcc_RESOURCES}) SET(_other_SOURCES OCCViewer.cxx OCCViewer_AISSelector.cxx + OCCViewer_AutoRotate.cxx OCCViewer_AxialScaleDlg.cxx OCCViewer_ClippingDlg.cxx OCCViewer_RayTracingDlg.cxx diff --git a/src/OCCViewer/OCCViewer_AutoRotate.cxx b/src/OCCViewer/OCCViewer_AutoRotate.cxx new file mode 100644 index 000000000..2c03bee21 --- /dev/null +++ b/src/OCCViewer/OCCViewer_AutoRotate.cxx @@ -0,0 +1,125 @@ +// Copyright (C) 2007-2023 CEA, EDF, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include "OCCViewer_AutoRotate.h" +#include "OCCViewer_ViewWindow.h" +#include "OCCViewer_ViewPort3d.h" + +#include + +#include + +#include +#include +#include +#include + + + +OCCViewer_AutoRotate::OCCViewer_AutoRotate(SUIT_ViewWindow* theWindow) + : SUIT_AutoRotate(theWindow) +{ +} + + +OCCViewer_AutoRotate::~OCCViewer_AutoRotate() +{ + OCCViewer_ViewWindow *aWnd = dynamic_cast(myWindow); + if (aWnd) { + OCCViewer_ViewPort3d* aViewPort = aWnd->getViewPort(); + if (aViewPort) { + aViewPort->stopRotation(); + } + } +} + + +bool OCCViewer_AutoRotate::startAnimation() +{ + const int LastIdx = 4; + const int PrevIdx = 10; + if (myLog.myHistorySize > PrevIdx) { + qint64 aStopTime = (QDateTime::currentMSecsSinceEpoch() - myLog.myTime[LastIdx]); + qint64 delta = (myLog.myTime[LastIdx] - myLog.myTime[PrevIdx]); + if (aStopTime < (qint64)100 && delta < (qint64)100) { + OCCViewer_ViewWindow *aWnd = dynamic_cast(myWindow); + if (aWnd) { + OCCViewer_ViewPort3d* aViewPort = aWnd->getViewPort(); + if (aViewPort) { + Handle(V3d_View) aView = aViewPort->getView(); + if ( !aView.IsNull() ) { + Standard_Real rx, ry; + aView->Size(rx, ry); + + Standard_Real dx=0., dy=0., dz=0.; + dx = (Standard_Real(this->myLog.myPosition[LastIdx].x()) - this->myLog.myPosition[PrevIdx].x()) * M_PI / rx; + dy = (this->myLog.myPosition[PrevIdx].y() - Standard_Real(this->myLog.myPosition[LastIdx].y())) * M_PI / ry; + dz = atan2(Standard_Real(this->myLog.myPosition[LastIdx].x())-rx/2., ry/2.-Standard_Real(this->myLog.myPosition[LastIdx].y())) + - atan2(this->myLog.myPosition[PrevIdx].x()-rx/2.,ry/2.-this->myLog.myPosition[PrevIdx].y()); + + Handle(Graphic3d_Camera) aCamera = aView->Camera(); + gp_Pnt aRCenter = aView->GravityPoint(); + gp_Dir aZAxis (aCamera->Direction().Reversed()); + gp_Dir aYAxis (aCamera->Up()); + gp_Dir aXAxis (aYAxis.Crossed (aZAxis)); + + gp_Trsf aRot[3], aTrsf; + aRot[0].SetRotation (gp_Ax1 (aRCenter, aYAxis), -dx); + aRot[1].SetRotation (gp_Ax1 (aRCenter, aXAxis), dy); + aRot[2].SetRotation (gp_Ax1 (aRCenter, aZAxis), dz); + aTrsf.Multiply (aRot[0]); + aTrsf.Multiply (aRot[1]); + aTrsf.Multiply (aRot[2]); + + gp_Quaternion quat = aTrsf.GetRotation(); + gp_Vec aAxis; + Standard_Real anAngle=0., aScale=1.; + quat.GetVectorAndAngle(aAxis, anAngle); + aScale = aView->Scale(); + // std::cout << "Axis=[" << aAxis.X() << " , " << aAxis.Y() << " , " << aAxis.Z() + // << "] Angle=" << anAngle * 180. / M_PI + // << " deg z-Angle=" << dz * 180. / M_PI << " deg Scale=" << aScale << std::endl; + if (anAngle != 0.) + aViewPort->setRotationAxis(aAxis, anAngle*3./aScale, dz*3./aScale); + } + } + return true; + } + } + } + + return false; +} + + +bool OCCViewer_AutoRotate::stopAnimation() +{ + OCCViewer_ViewWindow *aWnd = dynamic_cast(myWindow); + if (aWnd) { + OCCViewer_ViewPort3d* aViewPort = aWnd->getViewPort(); + if (aViewPort) { + aViewPort->stopRotation(); + return true; + } + } + return false; +} \ No newline at end of file diff --git a/src/OCCViewer/OCCViewer_AutoRotate.h b/src/OCCViewer/OCCViewer_AutoRotate.h new file mode 100644 index 000000000..4189bf425 --- /dev/null +++ b/src/OCCViewer/OCCViewer_AutoRotate.h @@ -0,0 +1,45 @@ +// Copyright (C) 2007-2023 CEA, EDF, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#ifndef OCCVIEWER_AUTOROTATE_H +#define OCCVIEWER_AUTOROTATE_H + +#include "OCCViewer.h" +#include "SUIT_AutoRotate.h" + + +class SUIT_ViewWindow; + + +class OCCVIEWER_EXPORT OCCViewer_AutoRotate : public SUIT_AutoRotate +{ + Q_OBJECT + +public: + OCCViewer_AutoRotate(SUIT_ViewWindow* theWindow); + virtual ~OCCViewer_AutoRotate(); + + virtual bool startAnimation(); + virtual bool stopAnimation(); +}; + +#endif diff --git a/src/OCCViewer/OCCViewer_ViewManager.cxx b/src/OCCViewer/OCCViewer_ViewManager.cxx index 7aef2009b..5be0268bf 100644 --- a/src/OCCViewer/OCCViewer_ViewManager.cxx +++ b/src/OCCViewer/OCCViewer_ViewManager.cxx @@ -21,6 +21,7 @@ // #include "OCCViewer_ViewManager.h" +#include "OCCViewer_ViewFrame.h" #include "OCCViewer_ViewWindow.h" #include "SUIT_Desktop.h" @@ -61,3 +62,28 @@ void OCCViewer_ViewManager::setChainedOperations( bool isChainedOperations ) { myIsChainedOperations = isChainedOperations; } + +bool OCCViewer_ViewManager::isAutoRotation() const +{ + return myIsAutoRotation; +} + +void OCCViewer_ViewManager::setAutoRotation( bool isAutoRotation ) +{ + myIsAutoRotation = isAutoRotation; + + // Update the auto rotation in all OCC views + QVector views = getViews(); + for ( int i = 0; i < views.count(); i++ ) + { + if ( views[i] ) { + OCCViewer_ViewWindow *aView = dynamic_cast(views[i]); + if (aView) { + OCCViewer_ViewWindow* aWnd = aView->getView(OCCViewer_ViewFrame::MAIN_VIEW); + if (aWnd) { + aWnd->enableAutoRotation(isAutoRotation); + } + } + } + } +} diff --git a/src/OCCViewer/OCCViewer_ViewManager.h b/src/OCCViewer/OCCViewer_ViewManager.h index fc0034ef0..f85d7ac8b 100644 --- a/src/OCCViewer/OCCViewer_ViewManager.h +++ b/src/OCCViewer/OCCViewer_ViewManager.h @@ -44,8 +44,12 @@ public: bool isChainedOperations() const; void setChainedOperations( bool ); + bool isAutoRotation() const; + void setAutoRotation( bool ); + private: bool myIsChainedOperations; + bool myIsAutoRotation; }; #endif diff --git a/src/OCCViewer/OCCViewer_ViewPort3d.cxx b/src/OCCViewer/OCCViewer_ViewPort3d.cxx index 322c86993..49c2250e7 100644 --- a/src/OCCViewer/OCCViewer_ViewPort3d.cxx +++ b/src/OCCViewer/OCCViewer_ViewPort3d.cxx @@ -39,7 +39,9 @@ #include #include #include +#include +#include #include #include "utilities.h" @@ -65,7 +67,9 @@ OCCViewer_ViewPort3d::OCCViewer_ViewPort3d( QWidget* parent, const Handle( V3d_V : OCCViewer_ViewPort( parent ), myBusy( true ), myScale( 1.0 ), - myIsAdvancedZoomingEnabled( false ) + myIsAdvancedZoomingEnabled( false ), + myIsRotating( false ), + myRotAngle( 0.0 ) { // VSR: 01/07/2010 commented to avoid SIGSEGV at SALOME exit //selectVisualId(); @@ -75,6 +79,7 @@ OCCViewer_ViewPort3d::OCCViewer_ViewPort3d( QWidget* parent, const Handle( V3d_V setDefaultParams(); myCursor = NULL; + myRotTimer = NULL; } /*! @@ -82,6 +87,13 @@ OCCViewer_ViewPort3d::OCCViewer_ViewPort3d( QWidget* parent, const Handle( V3d_V */ OCCViewer_ViewPort3d::~OCCViewer_ViewPort3d() { + if ( myRotTimer ) + { + myRotTimer->stop(); + delete myRotTimer; + myRotTimer = NULL; + } + if ( myCursor ) { delete myCursor; @@ -398,6 +410,9 @@ void OCCViewer_ViewPort3d::fitRect( const QRect& rect ) */ void OCCViewer_ViewPort3d::startZoomAtPoint( int x, int y ) { + // if (myIsRotating) + // stopRotation(); + if ( !activeView().IsNull() && isAdvancedZoomingEnabled() ) activeView()->StartZoomAtPoint( x, y ); } @@ -407,6 +422,9 @@ void OCCViewer_ViewPort3d::startZoomAtPoint( int x, int y ) */ void OCCViewer_ViewPort3d::zoom( int x0, int y0, int x, int y ) { + // if (myIsRotating) + // stopRotation(); + if ( !activeView().IsNull() ) { // as OCCT respects a sign of only dx, // but we want both signes to be taken into account @@ -424,6 +442,9 @@ void OCCViewer_ViewPort3d::zoom( int x0, int y0, int x, int y ) */ void OCCViewer_ViewPort3d::setCenter( int x, int y ) { + if (myIsRotating) + stopRotation(); + if ( !activeView().IsNull() ) { activeView()->Place( x, y, myScale ); emit vpTransformed( this ); @@ -435,6 +456,9 @@ void OCCViewer_ViewPort3d::setCenter( int x, int y ) */ void OCCViewer_ViewPort3d::pan( int dx, int dy ) { + if (myIsRotating) + stopRotation(); + if ( !activeView().IsNull() ) { activeView()->Pan( dx, dy, 1.0 ); emit vpTransformed( this ); @@ -448,28 +472,36 @@ void OCCViewer_ViewPort3d::startRotation( int x, int y, int theRotationPointType, const gp_Pnt& theSelectedPoint ) { + if (myIsRotating) + stopRotation(); + if ( !activeView().IsNull() ) { - //double gx, gy, gz; - //double gx = activeView()->gx; - //activeView()->Gravity(gx,gy,gz); + + Standard_Real zRotationThreshold, X, Y; + sx = x; sy = y; + activeView()->Size(X,Y); + rx = Standard_Real(activeView()->Convert(X)); + ry = Standard_Real(activeView()->Convert(Y)); + gp_Pnt centerPnt; switch ( theRotationPointType ) { case OCCViewer_ViewWindow::BBCENTER: + centerPnt = activeView()->GravityPoint(); + zRotation = Standard_False; + zRotationThreshold = 0.45; + if( zRotationThreshold > 0. ) { + Standard_Real dx = Abs(sx - rx/2.); + Standard_Real dy = Abs(sy - ry/2.); + Standard_Real dd = zRotationThreshold * (rx + ry)/2.; + if( dx > dd || dy > dd ) zRotation = Standard_True; + } activeView()->StartRotation( x, y, 0.45 ); break; case OCCViewer_ViewWindow::SELECTED: - sx = x; sy = y; - - double X,Y; - activeView()->Size(X,Y); - rx = Standard_Real(activeView()->Convert(X)); - ry = Standard_Real(activeView()->Convert(Y)); - activeView()->Rotate( 0., 0., 0., theSelectedPoint.X(),theSelectedPoint.Y(), theSelectedPoint.Z(), Standard_True ); - Standard_Real zRotationThreshold; zRotation = Standard_False; zRotationThreshold = 0.45; if( zRotationThreshold > 0. ) { @@ -535,6 +567,70 @@ void OCCViewer_ViewPort3d::endRotation() } } +/*! + Set the rotation axis and start automatic rotation +*/ +void OCCViewer_ViewPort3d::setRotationAxis(const gp_Vec& theAxis, double theAngle, double theZAngle) +{ + myRotAxis.SetLocation(activeView()->GravityPoint()); + if (zRotation) { + gp_Dir anAxisDir = activeView()->Camera()->Direction(); + myRotAxis.SetDirection(anAxisDir.Reversed()); + myRotAngle = theZAngle; + } + else { + myRotAxis.SetDirection(gp_Dir(theAxis)); + myRotAngle = theAngle; + } + if (!myRotTimer) { + myRotTimer = new QTimer(this); + myRotTimer->setSingleShot(true); + connect(myRotTimer, SIGNAL(timeout()), this, SLOT(updateRotation())); + } + else + myRotTimer->stop(); + + myIsRotating = true; + myLastRender = QDateTime::currentMSecsSinceEpoch(); + Handle(Graphic3d_Camera) aCamera = activeView()->Camera(); + gp_Trsf trsfRot; + trsfRot.SetRotation (myRotAxis, myRotAngle); + aCamera->Transform(trsfRot); + activeView()->SetCamera(aCamera); + myRotTimer->start(20); +} + +/*! + Stop the automatic rotation +*/ +void OCCViewer_ViewPort3d::stopRotation() +{ + myIsRotating = false; + if (myRotTimer) + myRotTimer->stop(); +} + +/*! + Update the automatic rotation animation +*/ +void OCCViewer_ViewPort3d::updateRotation() +{ + if (!myIsRotating) + return; + + qint64 curTime = QDateTime::currentMSecsSinceEpoch(); + double angle = myRotAngle * (curTime - myLastRender) / 100.; + Handle(Graphic3d_Camera) aCamera = activeView()->Camera(); + gp_Trsf trsfRot; + trsfRot.SetRotation(myRotAxis, angle); + aCamera->Transform(trsfRot); + activeView()->SetCamera(aCamera); + + myLastRender = curTime; + if (myRotTimer) + myRotTimer->start(20); +} + /*! Repaints the viewport. [ virtual protected ] */ @@ -584,6 +680,9 @@ void OCCViewer_ViewPort3d::fitAll( bool keepScale, bool /*withZ*/, bool upd ) if ( activeView().IsNull() ) return; + if (myIsRotating) + stopRotation(); + if ( keepScale ) myScale = activeView()->Scale(); @@ -599,6 +698,9 @@ void OCCViewer_ViewPort3d::fitAll( bool keepScale, bool /*withZ*/, bool upd ) */ void OCCViewer_ViewPort3d::reset() { + if (myIsRotating) + stopRotation(); + // double zsize = getZSize(); if ( !activeView().IsNull() ) { activeView()->Reset(); @@ -615,6 +717,9 @@ void OCCViewer_ViewPort3d::rotateXY( double degrees ) if ( activeView().IsNull() ) return; + if (myIsRotating) + stopRotation(); + int x = width()/2, y = height()/2; double X, Y, Z; activeView()->Convert( x, y, X, Y, Z ); diff --git a/src/OCCViewer/OCCViewer_ViewPort3d.h b/src/OCCViewer/OCCViewer_ViewPort3d.h index 6d57481d9..834f061bf 100644 --- a/src/OCCViewer/OCCViewer_ViewPort3d.h +++ b/src/OCCViewer/OCCViewer_ViewPort3d.h @@ -29,6 +29,8 @@ #include #include +#include + class QColor; class QString; class QRect; @@ -81,6 +83,12 @@ public: virtual void startRotation( int, int, int, const gp_Pnt& ); virtual void rotate( int, int, int, const gp_Pnt& ); virtual void endRotation(); + + // Set the rotation axis and start automatic rotation + void setRotationAxis(const gp_Vec& theAxis, double theAngle, double theZAngle); + // Stop the automatic rotation + void stopRotation(); + bool isBusy() {return myBusy;} // check that View Port is fully initialized void setAdvancedZoomingEnabled( const bool theState ) { myIsAdvancedZoomingEnabled = theState; } @@ -101,6 +109,7 @@ public slots: virtual bool synchronize( OCCViewer_ViewPort* ); private slots: + void updateRotation(); void repaintViewAfterMove(); protected: @@ -129,6 +138,12 @@ private: int myBgImgHeight; int myBgImgWidth; QCursor* myCursor; + // Fields for automatic rotation + gp_Ax1 myRotAxis; // The rotation axis + double myRotAngle; // The angular rotation speed + bool myIsRotating; // Whether rotation animation is active + qint64 myLastRender; // Timestamp of last paint event + QTimer* myRotTimer; // Rotation timer }; #ifdef WIN32 diff --git a/src/OCCViewer/OCCViewer_ViewWindow.cxx b/src/OCCViewer/OCCViewer_ViewWindow.cxx index 384bb8d78..551dffd93 100644 --- a/src/OCCViewer/OCCViewer_ViewWindow.cxx +++ b/src/OCCViewer/OCCViewer_ViewWindow.cxx @@ -32,6 +32,7 @@ #include "OCCViewer_CreateRestoreViewDlg.h" #include "OCCViewer_ClipPlane.h" #include "OCCViewer_SetRotationPointDlg.h" +#include "OCCViewer_AutoRotate.h" #include "OCCViewer_AxialScaleDlg.h" #include "OCCViewer_CubeAxesDlg.h" #include "OCCViewer_ClippingDlg.h" @@ -250,6 +251,7 @@ const char* imageCrossCursor[] = { OCCViewer_ViewWindow::OCCViewer_ViewWindow( SUIT_Desktop* theDesktop, OCCViewer_Viewer* theModel ) : SUIT_ViewWindow( theDesktop ) +, myAutoRotate( 0 ) { myModel = theModel; myRestoreFlag = 0; @@ -284,6 +286,7 @@ OCCViewer_ViewWindow::OCCViewer_ViewWindow( SUIT_Desktop* theDesktop, */ OCCViewer_ViewWindow::~OCCViewer_ViewWindow() { + if (myAutoRotate) delete myAutoRotate; endDrawRect(); qDeleteAll( mySketchers ); } @@ -468,6 +471,7 @@ void OCCViewer_ViewWindow::vpMousePressEvent( QMouseEvent* theEvent ) { myStartX = theEvent->x(); myStartY = theEvent->y(); + myStartTime = QDateTime::currentMSecsSinceEpoch(); int anInteractionStyle = interactionStyle(); // in "key free" interaction style zoom operation is activated by two buttons (simultaneously pressed), @@ -514,6 +518,7 @@ void OCCViewer_ViewWindow::vpMousePressEvent( QMouseEvent* theEvent ) else if ( theEvent->button() == Qt::LeftButton ) { myViewPort->startRotation(myStartX, myStartY, myCurrPointType, mySelectedPoint); emit vpTransformationStarted ( ROTATE ); + emit vpStartRotate(myStartX, myStartY, myStartTime); } break; @@ -537,6 +542,7 @@ void OCCViewer_ViewWindow::vpMousePressEvent( QMouseEvent* theEvent ) case ROTATE: activateRotation(); myViewPort->startRotation(myStartX, myStartY, myCurrPointType, mySelectedPoint); + emit vpStartRotate(myStartX, myStartY, myStartTime); break; default: if ( myRotationPointSelection ) @@ -941,6 +947,7 @@ void OCCViewer_ViewWindow::vpMouseMoveEvent( QMouseEvent* theEvent ) case ROTATE: activateRotation(); myViewPort->startRotation(myStartX, myStartY, myCurrPointType, mySelectedPoint); + emit vpStartRotate(myStartX, myStartY, myStartTime); break; default: break; @@ -949,9 +956,11 @@ void OCCViewer_ViewWindow::vpMouseMoveEvent( QMouseEvent* theEvent ) myCurrX = theEvent->x(); myCurrY = theEvent->y(); + myCurrTime = QDateTime::currentMSecsSinceEpoch(); switch (myOperation) { case ROTATE: myViewPort->rotate(myCurrX, myCurrY, myCurrPointType, mySelectedPoint); + emit vpRotate(myCurrX, myCurrY, myCurrTime); break; case ZOOMVIEW: @@ -1078,7 +1087,11 @@ void OCCViewer_ViewWindow::vpMouseReleaseEvent(QMouseEvent* theEvent) } break; case ROTATE: + myCurrX = theEvent->x(); + myCurrY = theEvent->y(), + myCurrTime = QDateTime::currentMSecsSinceEpoch(); myViewPort->endRotation(); + emit vpEndRotate(myCurrX, myCurrY, myCurrTime); resetState(); break; @@ -3852,3 +3865,15 @@ void OCCViewer_ViewWindow::setAutomaticZoom(const bool isOn) myAutomaticZoom = isOn; } + +void OCCViewer_ViewWindow::enableAutoRotation( const bool isEnable ) +{ + SUIT_ViewWindow::enableAutoRotation(isEnable); + if (myAutoRotate) { + delete myAutoRotate; + myAutoRotate = nullptr; + } + if (isEnable) { + myAutoRotate = new OCCViewer_AutoRotate(this); + } +} diff --git a/src/OCCViewer/OCCViewer_ViewWindow.h b/src/OCCViewer/OCCViewer_ViewWindow.h index fc1728cd6..2026d1238 100644 --- a/src/OCCViewer/OCCViewer_ViewWindow.h +++ b/src/OCCViewer/OCCViewer_ViewWindow.h @@ -34,6 +34,7 @@ class QtxRectRubberBand; class SUIT_Desktop; class OCCViewer_ViewPort3d; class OCCViewer_ViewSketcher; +class OCCViewer_AutoRotate; class OCCViewer_AxialScaleDlg; class OCCViewer_SetRotationPointDlg; class OCCViewer_Viewer; @@ -256,6 +257,8 @@ public: virtual bool isAutomaticZoom() const; virtual void setAutomaticZoom( const bool ); + virtual void enableAutoRotation( const bool ); + void setTransformEnabled( const OperationType, const bool ); bool transformEnabled( const OperationType ) const; @@ -413,12 +416,14 @@ protected: gp_Pnt mySelectedPoint; bool myRotationPointSelection; - int myRestoreFlag; + int myRestoreFlag; - int myStartX; - int myStartY; - int myCurrX; - int myCurrY; + int myStartX; + int myStartY; + qint64 myStartTime; + int myCurrX; + int myCurrY; + qint64 myCurrTime; bool myEventStarted; // set when transformation is in process bool myCursorIsHand; @@ -441,6 +446,8 @@ private: QtxRectRubberBand* myRectBand; //!< selection rectangle rubber band + OCCViewer_AutoRotate *myAutoRotate; + bool mySelectionEnabled; bool myPreselectionEnabled; int myInteractionStyle; diff --git a/src/SUIT/CMakeLists.txt b/src/SUIT/CMakeLists.txt index 7320c8537..bad1fd6e3 100644 --- a/src/SUIT/CMakeLists.txt +++ b/src/SUIT/CMakeLists.txt @@ -41,6 +41,7 @@ SET(_moc_HEADERS SUIT_Accel.h SUIT_ActionOperation.h SUIT_Application.h + SUIT_AutoRotate.h SUIT_DataBrowser.h SUIT_DataObject.h SUIT_Desktop.h @@ -108,6 +109,7 @@ SET(_other_SOURCES SUIT_Accel.cxx SUIT_ActionOperation.cxx SUIT_Application.cxx + SUIT_AutoRotate.cxx SUIT_CameraProperties.cxx SUIT_DataBrowser.cxx SUIT_DataObject.cxx diff --git a/src/SUIT/SUIT_AutoRotate.cxx b/src/SUIT/SUIT_AutoRotate.cxx new file mode 100644 index 000000000..2957c247b --- /dev/null +++ b/src/SUIT/SUIT_AutoRotate.cxx @@ -0,0 +1,121 @@ +// Copyright (C) 2007-2023 CEA, EDF, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include "SUIT_AutoRotate.h" +#include "SUIT_ViewWindow.h" + +#include +#include +#include +#include + + + +SUIT_AutoRotate::SUIT_AutoRotate(SUIT_ViewWindow* theWindow) + : QObject() + , myWindow(theWindow) +{ + initialize(); + + if (myWindow) { + // Let's intercept all view rotation relevant signals inside this class + connect( myWindow, SIGNAL( vpStartRotate(int, int, qint64) ), this, SLOT( onStartRotate(int, int, qint64) ) ); + connect( myWindow, SIGNAL( vpRotate(int, int, qint64) ), this, SLOT( onRotate(int, int, qint64) ) ); + connect( myWindow, SIGNAL( vpEndRotate(int, int, qint64) ), this, SLOT( onEndRotate(int, int, qint64) ) ); + connect( myWindow, SIGNAL( mousePressed(SUIT_ViewWindow*, QMouseEvent*) ), this, SLOT( onStopRotate() ) ); + } +} + + +SUIT_AutoRotate::~SUIT_AutoRotate() +{ + delete [] myLog.myPosition; + delete [] myLog.myTime; +} + + +void SUIT_AutoRotate::initialize() +{ + myLog.mySize = 16; + myLog.myPosition = new QPoint [16]; + myLog.myTime = new qint64 [16]; + myLog.myHistorySize = 0; +} + + +void SUIT_AutoRotate::onStartRotate(int theMouseX, int theMouseY, qint64 theTime) +{ + myLog.myHistorySize = 0; + addToLog(QPoint(theMouseX, theMouseY), theTime); +} + + +void SUIT_AutoRotate::onRotate(int theMouseX, int theMouseY, qint64 theTime) +{ + addToLog(QPoint(theMouseX, theMouseY), theTime); +} + + +void SUIT_AutoRotate::onEndRotate(int theMouseX, int theMouseY, qint64 theTime) +{ + startAnimation(); +} + + +void SUIT_AutoRotate::onStopRotate() +{ + stopAnimation(); +} + + +void SUIT_AutoRotate::addToLog(const QPoint& thePos, qint64 theTime) +{ + if (myLog.myHistorySize > 0 && thePos == myLog.myPosition[0]) { + return; + } + + int aLastIdx = myLog.myHistorySize; + // If we have filled up the log, throw away the last item + if (aLastIdx == myLog.mySize) { aLastIdx--; } + + for (int i = aLastIdx; i > 0; i--) { + myLog.myPosition[i] = myLog.myPosition[i-1]; + myLog.myTime[i] = myLog.myTime[i-1]; + } + + myLog.myPosition[0] = thePos; + myLog.myTime[0] = theTime; + if (myLog.myHistorySize < myLog.mySize) + myLog.myHistorySize++; +} + + +bool SUIT_AutoRotate::startAnimation() +{ + // override this method in derived classes +} + + +bool SUIT_AutoRotate::stopAnimation() +{ + // override this method in derived classes +} diff --git a/src/SUIT/SUIT_AutoRotate.h b/src/SUIT/SUIT_AutoRotate.h new file mode 100644 index 000000000..d92eb2894 --- /dev/null +++ b/src/SUIT/SUIT_AutoRotate.h @@ -0,0 +1,67 @@ +// Copyright (C) 2007-2023 CEA, EDF, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#ifndef SUIT_AUTOROTATE_H +#define SUIT_AUTOROTATE_H + +#include "SUIT.h" +#include + + +class SUIT_ViewWindow; +class QMouseEvent; +class QPoint; + + +class SUIT_EXPORT SUIT_AutoRotate : public QObject +{ + Q_OBJECT + +public: + SUIT_AutoRotate(SUIT_ViewWindow* theWindow); + virtual ~SUIT_AutoRotate(); + + virtual void initialize(); + + virtual bool startAnimation(); + virtual bool stopAnimation(); + +public slots: + virtual void onStartRotate(int theMouseX, int theMouseY, qint64 theTime); + virtual void onRotate(int theMouseX, int theMouseY, qint64 theTime); + virtual void onEndRotate(int theMouseX, int theMouseY, qint64 theTime); + virtual void onStopRotate(); + +protected: + void addToLog(const QPoint& thePos, qint64 theTime); + + struct { // tracking mouse movement in a log + short mySize; + short myHistorySize; + QPoint* myPosition; + qint64* myTime; + } myLog; + + SUIT_ViewWindow* myWindow; +}; + +#endif diff --git a/src/SUIT/SUIT_ViewWindow.cxx b/src/SUIT/SUIT_ViewWindow.cxx index 82819c820..244567713 100644 --- a/src/SUIT/SUIT_ViewWindow.cxx +++ b/src/SUIT/SUIT_ViewWindow.cxx @@ -329,6 +329,19 @@ bool SUIT_ViewWindow::dropDownButtons() const return myIsDropDown; } +void SUIT_ViewWindow::enableAutoRotation( const bool aEnable ) +{ + myIsAutoRotation = aEnable; +} + +/*! + \return automatic rotation enable flag +*/ +bool SUIT_ViewWindow::isAutoRotationEnabled() const +{ + return myIsAutoRotation; +} + /*! \return window unique identifier */ diff --git a/src/SUIT/SUIT_ViewWindow.h b/src/SUIT/SUIT_ViewWindow.h index 160409d86..b3712c2de 100644 --- a/src/SUIT/SUIT_ViewWindow.h +++ b/src/SUIT/SUIT_ViewWindow.h @@ -72,6 +72,9 @@ public: virtual void setDropDownButtons( bool ); bool dropDownButtons() const; + virtual void enableAutoRotation( const bool ); + virtual bool isAutoRotationEnabled() const; + virtual SUIT_CameraProperties cameraProperties(); public slots: @@ -90,7 +93,10 @@ signals: void keyReleased( SUIT_ViewWindow*, QKeyEvent* ); void contextMenuRequested( QContextMenuEvent *e ); void viewModified( SUIT_ViewWindow* ); - + void vpStartRotate( int, int, qint64 ); + void vpRotate( int, int, qint64 ); + void vpEndRotate( int, int, qint64 ); + protected: void closeEvent( QCloseEvent* ); virtual void contextMenuEvent( QContextMenuEvent* ); @@ -115,6 +121,7 @@ private: QtxActionToolMgr* myToolMgr; bool myIsDropDown; + bool myIsAutoRotation; ActionsMap myMultiActions; QAction* mySyncAction; }; -- 2.30.2