From 4f6d61c2cde6fddd4a6329121be077f46aea38c5 Mon Sep 17 00:00:00 2001 From: apl Date: Fri, 7 Oct 2016 21:18:28 +0300 Subject: [PATCH] Interactive annotations --- resources/SalomeApp.xml.in | 2 +- src/GEOMGUI/GEOM_Displayer.cxx | 5 +- src/MeasureGUI/CMakeLists.txt | 3 + src/MeasureGUI/MeasureGUI_AnnotationDlg.cxx | 24 ++ src/MeasureGUI/MeasureGUI_AnnotationDlg.h | 3 + .../MeasureGUI_AnnotationInteractor.cxx | 306 ++++++++++++++++++ .../MeasureGUI_AnnotationInteractor.h | 110 +++++++ src/OBJECT/GEOM_Annotation.cxx | 250 +++++++++++--- src/OBJECT/GEOM_Annotation.hxx | 57 +++- 9 files changed, 704 insertions(+), 56 deletions(-) mode change 100644 => 100755 src/MeasureGUI/MeasureGUI_AnnotationDlg.cxx mode change 100644 => 100755 src/MeasureGUI/MeasureGUI_AnnotationDlg.h create mode 100755 src/MeasureGUI/MeasureGUI_AnnotationInteractor.cxx create mode 100755 src/MeasureGUI/MeasureGUI_AnnotationInteractor.h diff --git a/resources/SalomeApp.xml.in b/resources/SalomeApp.xml.in index 9d522cd69..0256007de 100755 --- a/resources/SalomeApp.xml.in +++ b/resources/SalomeApp.xml.in @@ -102,7 +102,7 @@ - + diff --git a/src/GEOMGUI/GEOM_Displayer.cxx b/src/GEOMGUI/GEOM_Displayer.cxx index 9bdad8b6b..e66324174 100755 --- a/src/GEOMGUI/GEOM_Displayer.cxx +++ b/src/GEOMGUI/GEOM_Displayer.cxx @@ -1404,7 +1404,7 @@ void GEOM_Displayer::updateShapeAnnotations( const Handle(SALOME_InteractiveObje SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); - const QFont aFont = aResMgr->fontValue( "Geometry", "shape_annotation_font", QFont( "Arial", 14 ) ); + const QFont aFont = aResMgr->fontValue( "Geometry", "shape_annotation_font", QFont( "Y14.5M-2009", 24 ) ); const QColor aFontColor = aResMgr->colorValue( "Geometry", "shape_annotation_font_color", QColor( 255, 255, 255 ) ); const QColor aLineColor = aResMgr->colorValue( "Geometry", "shape_annotation_line_color", QColor( 255, 255, 255 ) ); const double aLineWidth = aResMgr->doubleValue( "Geometry", "shape_annotation_line_width", 1.0 ); @@ -1439,7 +1439,8 @@ void GEOM_Displayer::updateShapeAnnotations( const Handle(SALOME_InteractiveObje const Quantity_Color aOcctLineColor( aLineColor.redF(), aLineColor.greenF(), aLineColor.blueF(), Quantity_TOC_RGB ); const Standard_Real aFontHeight = aFont.pixelSize() != -1 ? aFont.pixelSize() : aFont.pointSize(); - aPresentation->SetTextHeight( aFont.pixelSize() != -1 ? aFont.pixelSize() : aFont.pointSize() ); + aPresentation->SetFont( TCollection_AsciiString( aFont.family().toLatin1().data() ) ); + aPresentation->SetTextHeight( aFontHeight ); aPresentation->SetTextColor( Quantity_Color( aFontColor.redF(), aFontColor.greenF(), aFontColor.blueF(), Quantity_TOC_RGB ) ); aPresentation->SetLineColor( Quantity_Color( aLineColor.redF(), aLineColor.greenF(), aLineColor.blueF(), Quantity_TOC_RGB ) ); aPresentation->SetLineWidth( aLineWidth ); diff --git a/src/MeasureGUI/CMakeLists.txt b/src/MeasureGUI/CMakeLists.txt index a4df31875..7bbd75177 100755 --- a/src/MeasureGUI/CMakeLists.txt +++ b/src/MeasureGUI/CMakeLists.txt @@ -89,6 +89,7 @@ SET(MeasureGUI_HEADERS MeasureGUI_BndBoxDlg.h MeasureGUI_DistanceDlg.h MeasureGUI_AnnotationDlg.h + MeasureGUI_AnnotationInteractor.h MeasureGUI_AngleDlg.h MeasureGUI_MaxToleranceDlg.h MeasureGUI_WhatisDlg.h @@ -118,6 +119,7 @@ SET(_moc_HEADERS MeasureGUI_BndBoxDlg.h MeasureGUI_DistanceDlg.h MeasureGUI_AnnotationDlg.h + MeasureGUI_AnnotationInteractor.h MeasureGUI_AngleDlg.h MeasureGUI_MaxToleranceDlg.h MeasureGUI_WhatisDlg.h @@ -157,6 +159,7 @@ SET(MeasureGUI_SOURCES MeasureGUI_BndBoxDlg.cxx MeasureGUI_DistanceDlg.cxx MeasureGUI_AnnotationDlg.cxx + MeasureGUI_AnnotationInteractor.cxx MeasureGUI_AngleDlg.cxx MeasureGUI_MaxToleranceDlg.cxx MeasureGUI_WhatisDlg.cxx diff --git a/src/MeasureGUI/MeasureGUI_AnnotationDlg.cxx b/src/MeasureGUI/MeasureGUI_AnnotationDlg.cxx old mode 100644 new mode 100755 index 705877db3..2afd00811 --- a/src/MeasureGUI/MeasureGUI_AnnotationDlg.cxx +++ b/src/MeasureGUI/MeasureGUI_AnnotationDlg.cxx @@ -24,6 +24,7 @@ #include "MeasureGUI.h" #include "MeasureGUI_AnnotationDlg.h" +#include "MeasureGUI_AnnotationInteractor.h" #include #include @@ -192,6 +193,9 @@ MeasureGUI_AnnotationDlg::MeasureGUI_AnnotationDlg(GeometryGUI* theGeometryGUI, connect(buttonOk(), SIGNAL(clicked()), this, SLOT(ClickOnOk())); connect(buttonApply(), SIGNAL(clicked()), this, SLOT(ClickOnApply())); + myInteractor = new MeasureGUI_AnnotationInteractor( theGeometryGUI, parent ); + myInteractor->Enable(); + Init(); //updateState(); } @@ -519,6 +523,26 @@ SALOME_Prs* MeasureGUI_AnnotationDlg::buildPrs() { Handle (GEOM_Annotation) aPresentation = new GEOM_Annotation(); + SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); + const QFont aFont = aResMgr->fontValue( "Geometry", "shape_annotation_font", QFont( "Y14.5M-2009", 24 ) ); + const QColor aFontColor = aResMgr->colorValue( "Geometry", "shape_annotation_font_color", QColor( 255, 255, 255 ) ); + const QColor aLineColor = aResMgr->colorValue( "Geometry", "shape_annotation_line_color", QColor( 255, 255, 255 ) ); + const double aLineWidth = aResMgr->doubleValue( "Geometry", "shape_annotation_line_width", 1.0 ); + const int aLineStyle = aResMgr->integerValue( "Geometry", "shape_annotation_line_style", 0 ); + const bool isAutoHide = aResMgr->booleanValue( "Geometry", "shape_annotation_autohide", false ); + + const Quantity_Color aOcctFontColor( aFontColor.redF(), aFontColor.greenF(), aFontColor.blueF(), Quantity_TOC_RGB ); + const Quantity_Color aOcctLineColor( aLineColor.redF(), aLineColor.greenF(), aLineColor.blueF(), Quantity_TOC_RGB ); + const Standard_Real aFontHeight = aFont.pixelSize() != -1 ? aFont.pixelSize() : aFont.pointSize(); + + aPresentation->SetFont( TCollection_AsciiString( aFont.family().toLatin1().data() ) ); + aPresentation->SetTextHeight( aFontHeight ); + aPresentation->SetTextColor( Quantity_Color( aFontColor.redF(), aFontColor.greenF(), aFontColor.blueF(), Quantity_TOC_RGB ) ); + aPresentation->SetLineColor( Quantity_Color( aLineColor.redF(), aLineColor.greenF(), aLineColor.blueF(), Quantity_TOC_RGB ) ); + aPresentation->SetLineWidth( aLineWidth ); + aPresentation->SetLineStyle( static_cast( aLineStyle ) ); + aPresentation->SetAutoHide( isAutoHide ? Standard_True : Standard_False ); + TopoDS_Shape aShape; GEOMBase::GetShape(myShape.get(), aShape); gp_Ax3 aShapeLCS = gp_Ax3().Transformed(aShape.Location().Transformation()); diff --git a/src/MeasureGUI/MeasureGUI_AnnotationDlg.h b/src/MeasureGUI/MeasureGUI_AnnotationDlg.h old mode 100644 new mode 100755 index 6c613c908..686cee65d --- a/src/MeasureGUI/MeasureGUI_AnnotationDlg.h +++ b/src/MeasureGUI/MeasureGUI_AnnotationDlg.h @@ -46,6 +46,7 @@ class QLineEdit; class QPushButton; class QComboBox; class SalomeApp_IntSpinBox; +class MeasureGUI_AnnotationInteractor; //================================================================================= // class : MeasureGUI_AnnotationDlg @@ -106,6 +107,8 @@ private: QPushButton* mySubShapeSelBtn; QLineEdit* mySubShapeName; + + MeasureGUI_AnnotationInteractor* myInteractor; }; #endif diff --git a/src/MeasureGUI/MeasureGUI_AnnotationInteractor.cxx b/src/MeasureGUI/MeasureGUI_AnnotationInteractor.cxx new file mode 100755 index 000000000..9e1c0e3c5 --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_AnnotationInteractor.cxx @@ -0,0 +1,306 @@ +// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, 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 +// + +// GEOM GEOMGUI : GUI for Geometry component +// File : MeasureGUI_AnnotationInteractor.cxx +// Author : Anton POLETAEV, Open CASCADE S.A.S. + +#include "MeasureGUI_AnnotationInteractor.h" + +// SALOME includes +#include +#include +#include +#include +#include +#include +#include +#include + +// Qt includes +#include + +// OCCT includes +#include + +//================================================================================= +// function : Constructor +// purpose : +//================================================================================= +MeasureGUI_AnnotationInteractor::MeasureGUI_AnnotationInteractor( GeometryGUI* theGUI, + QObject* theParent ) +: QObject( theParent ), + myGeomGUI( theGUI ), + myIsEnabled( false ), + myVM( NULL ), + myViewer( NULL ), + myActiveViewPort( NULL ) +{ +} + +//================================================================================= +// function : Deactivate +// purpose : +//================================================================================= +MeasureGUI_AnnotationInteractor::~MeasureGUI_AnnotationInteractor() +{ + if ( myActiveViewPort ) + { + myActiveViewPort->releaseMouse(); + myActiveViewPort = NULL; + } + + Disable(); +} + +//================================================================================= +// function : Enable +// purpose : Enables event processing and interaction handlers. +//================================================================================= +void MeasureGUI_AnnotationInteractor::Enable() +{ + if ( myIsEnabled ) + { + return; + } + + myIsEnabled = true; + + // install event filtering on viewer windows + SalomeApp_Application* anApp = myGeomGUI->getApp(); + if ( !anApp ) + { + return; + } + + myVM = (OCCViewer_ViewManager*) anApp->getViewManager( OCCViewer_Viewer::Type(), false ); + myViewer = (OCCViewer_Viewer*) myVM->getViewModel(); + if ( !myVM || !myViewer ) + { + return; + } + + connect( myVM, SIGNAL( viewCreated( SUIT_ViewWindow* ) ), SLOT( OnViewCreated( SUIT_ViewWindow* ) ) ); + connect( myVM, SIGNAL( deleteView ( SUIT_ViewWindow* ) ), SLOT( OnViewRemoved( SUIT_ViewWindow* ) ) ); + + QVector aViews = myVM->getViews(); + QVector::iterator aViewIt = aViews.begin(); + for ( ; aViewIt != aViews.end(); ++aViewIt ) + { + ConnectView( *aViewIt ); + } +} + +//================================================================================= +// function : Disable +// purpose : Disables event processing and interaction handlers. +//================================================================================= +void MeasureGUI_AnnotationInteractor::Disable() +{ + if ( !myIsEnabled ) + { + return; + } + + myIsEnabled = false; + + // remove event filtering from viewer windows + QVector aViews = myVM->getViews(); + QVector::iterator aViewIt = aViews.begin(); + for ( ; aViewIt != aViews.end(); ++aViewIt ) + { + DisconnectView( *aViewIt ); + } + + if ( myActiveViewPort ) + { + myActiveViewPort->releaseMouse(); + myActiveViewPort = NULL; + } + + myActiveIO.Nullify(); +} + +//================================================================================= +// function : ConnectView +// purpose : Connect interactor's event handler to the view window given. +//================================================================================= +void MeasureGUI_AnnotationInteractor::ConnectView( SUIT_ViewWindow* theView ) +{ + ( (OCCViewer_ViewWindow*) theView )->getViewPort()->installEventFilter( this ); +} + +//================================================================================= +// function : DisconnectView +// purpose : Disconnect interactor's event handler from the view window given. +//================================================================================= +void MeasureGUI_AnnotationInteractor::DisconnectView( SUIT_ViewWindow* theView ) +{ + ( (OCCViewer_ViewWindow*) theView )->getViewPort()->removeEventFilter( this ); +} + +//================================================================================= +// function : OnViewCreated +// purpose : Handler for signal coming from GUI layer. +//================================================================================= +void MeasureGUI_AnnotationInteractor::OnViewCreated( SUIT_ViewWindow* theView ) +{ + ConnectView( theView ); +} + +//================================================================================= +// function : OnViewRemoved +// purpose : Handler for signal coming from GUI layer. +//================================================================================= +void MeasureGUI_AnnotationInteractor::OnViewRemoved( SUIT_ViewWindow* theView ) +{ + DisconnectView( theView ); +} + +//================================================================================= +// function : eventFilter +// purpose : Hooks and process events from OCCT viewer prior to their coming into the base viewer class. +//================================================================================= +bool MeasureGUI_AnnotationInteractor::eventFilter( QObject* theObject, QEvent* theEvent ) +{ + OCCViewer_ViewPort3d* aViewPort = (OCCViewer_ViewPort3d*)theObject; + + const Handle(V3d_View) aView3d = aViewPort->getView(); + + switch( theEvent->type() ) + { + // ------------------------------------------------------------------------ + // Start dragging ("grab") event + // ------------------------------------------------------------------------ + case QEvent::MouseButtonPress : + { + QMouseEvent* aMouseEv = dynamic_cast( theEvent ); + + if ( !( aMouseEv->buttons() & Qt::LeftButton ) ) + { + return false; + } + + const Handle(AIS_InteractiveContext) anAISContext = myViewer->getAISContext(); + + anAISContext->MoveTo( aMouseEv->x(), aMouseEv->y(), aView3d ); + + if ( !anAISContext->HasDetected() ) + { + return false; + } + + const Handle(SelectMgr_EntityOwner) aDetected = anAISContext->DetectedOwner(); + + if( aDetected.IsNull() ) + { + return false; + } + + const Handle(GEOM_Annotation) aAnnotation = + Handle(GEOM_Annotation)::DownCast( aDetected->Selectable() ); + + if ( aAnnotation.IsNull() ) + { + return false; + } + + myStartPoint = aMouseEv->pos(); + mySelection.Clear(); + + for ( anAISContext->InitSelected(); anAISContext->MoreSelected(); anAISContext->NextSelected() ) + { + mySelection.Append( anAISContext->SelectedOwner() ); + } + + anAISContext->ClearSelected( Standard_False ); + anAISContext->AddOrRemoveSelected( aDetected ); + + myActiveViewPort = aViewPort; + myActiveViewPort->grabMouse(); + myActiveIO = aAnnotation; + myActiveIO->BeginDrag(); + + return true; + } + + // ------------------------------------------------------------------------ + // Perform dragging operation + // ------------------------------------------------------------------------ + case QEvent::MouseMove : + { + QMouseEvent* aMouseEv = (QMouseEvent*) theEvent; + + if ( !myActiveIO.IsNull() ) + { + const Handle(AIS_InteractiveContext) anAISContext = myViewer->getAISContext(); + const QPoint aDelta = aMouseEv->pos() - myStartPoint; + myActiveIO->Drag( aDelta.x(), (-aDelta.y()), aView3d ); + anAISContext->Update( myActiveIO, Standard_False ); + anAISContext->UpdateCurrentViewer(); + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + // Stop dragging operation + // ------------------------------------------------------------------------ + case QEvent::FocusOut : + case QEvent::MouseButtonRelease : + { + QMouseEvent* aMouseEv = (QMouseEvent*) theEvent; + + if ( myActiveViewPort ) + { + myActiveViewPort->releaseMouse(); + myActiveViewPort = NULL; + } + if ( !myActiveIO.IsNull() ) + { + myActiveIO->EndDrag(); + + const Handle(AIS_InteractiveContext) anAISContext = myViewer->getAISContext(); + + anAISContext->ClearSelected( Standard_False ); + SelectMgr_SequenceOfOwner::Iterator anIt( mySelection ); + for( ; anIt.More(); anIt.Next() ) + { + anAISContext->AddOrRemoveSelected( anIt.Value(), Standard_False ); + } + + anAISContext->Update( myActiveIO, Standard_False ); + anAISContext->UpdateCurrentViewer(); + anAISContext->MoveTo( aMouseEv->pos().x(), aMouseEv->pos().y(), aView3d ); + + mySelection.Clear(); + myActiveIO.Nullify(); + return (theEvent->type() == QEvent::MouseButtonRelease); + } + + return false; + } + + default: return false; + } +} diff --git a/src/MeasureGUI/MeasureGUI_AnnotationInteractor.h b/src/MeasureGUI/MeasureGUI_AnnotationInteractor.h new file mode 100755 index 000000000..ed9bc0b5c --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_AnnotationInteractor.h @@ -0,0 +1,110 @@ +// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, 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 +// + +// GEOM GEOMGUI : GUI for Geometry component +// File : MeasureGUI_AnnotationInteractor.h +// Author : Anton POLETAEV, Open CASCADE S.A.S. +// +#ifndef MEASUREGUI_ANNOTATIONINTERACTOR_H +#define MEASUREGUI_ANNOTATIONINTERACTOR_H + +#include +#include +#include +#include +#include + +class GeometryGUI; +class OCCViewer_Viewer; +class OCCViewer_ViewManager; +class OCCViewer_ViewPort3d; +class SUIT_ViewWindow; + +/*! + * \class MeasureGUI_AnnotationInteractor + * \brief Class implementing logical layer for interactive dragging of annotation + * labels. It includes two components: listener for GUI events occuring + * inside of OCCT 3D viewer and processor for hooked events to perform + * interactive modification of the selected annotation within current + * AIS context. + */ +class MeasureGUI_AnnotationInteractor : public QObject +{ + Q_OBJECT + +public: + + //! Constructor. + //! Connects to existing viewer/view windows to process events. + //! \param theGUI [in] the geometry module's GUI interface. + //! \param theOwner [in] the owner of the instance. + MeasureGUI_AnnotationInteractor( GeometryGUI* theGUI, QObject* theOwner ); + + //! Destructor. + virtual ~MeasureGUI_AnnotationInteractor(); + +public: + + //! Enables event processing and interaction handlers. + void Enable(); + + //! Disables event processing and interaction handlers. + void Disable(); + +protected: + + //! Connect interactor's event handler to the view window given. + void ConnectView( SUIT_ViewWindow* theWindow ); + + //! Disconnect interactor's event handler from the view window given. + void DisconnectView( SUIT_ViewWindow* theWindow ); + +protected slots: + + //! Handler for signal coming from GUI layer. + void OnViewCreated( SUIT_ViewWindow* ); + + //! Handler for signal coming from GUI layer. + void OnViewRemoved( SUIT_ViewWindow* ); + +protected: + + //! Hooks and process events from OCCT viewer prior to their coming into the base viewer class. + //! It handles the events coming to viewport and identifies whether the events can + //! invoke an interaction operation or not. If yes, the operation is performed within the + //! interactor class and events are "accepted". Otherwise, the events are passed to + //! viewer's subroutines. + virtual bool eventFilter( QObject*, QEvent* ); + +private: + + GeometryGUI* myGeomGUI; + bool myIsEnabled; + OCCViewer_ViewManager* myVM; + OCCViewer_Viewer* myViewer; + OCCViewer_ViewPort3d* myActiveViewPort; + Handle(GEOM_Annotation) myActiveIO; + SelectMgr_SequenceOfOwner mySelection; + QPoint myStartPoint; +}; + +#endif diff --git a/src/OBJECT/GEOM_Annotation.cxx b/src/OBJECT/GEOM_Annotation.cxx index 92e26b895..9dfdfebd5 100755 --- a/src/OBJECT/GEOM_Annotation.cxx +++ b/src/OBJECT/GEOM_Annotation.cxx @@ -43,11 +43,13 @@ #include #include #include +#include #include #include #include #include #include +#include IMPLEMENT_STANDARD_RTTIEXT( GEOM_Annotation, AIS_InteractiveObject ) @@ -64,6 +66,7 @@ GEOM_Annotation::GEOM_Annotation() : AIS_InteractiveObject() SetZLayer( Graphic3d_ZLayerId_Top ); SetAutoHide( Standard_True ); SetHilightMode( HighlightAll ); + SetMutable( Standard_True ); Handle(Prs3d_TextAspect) aTextAspect = new Prs3d_TextAspect(); aTextAspect->SetHeight( 20.0 ); @@ -73,6 +76,10 @@ GEOM_Annotation::GEOM_Annotation() : AIS_InteractiveObject() Handle(Prs3d_LineAspect) aLineAspect = new Prs3d_LineAspect( Quantity_NOC_WHITE, Aspect_TOL_SOLID, 1.0 ); myDrawer->SetLineAspect( aLineAspect ); + + Handle(Prs3d_PointAspect) aPointAspect = + new Prs3d_PointAspect( Aspect_TOM_POINT, Quantity_NOC_WHITE, 4.0 ); + myDrawer->SetPointAspect( aPointAspect ); } // ======================================================================= @@ -94,10 +101,30 @@ void GEOM_Annotation::SetText( const TCollection_ExtendedString& theText ) // purpose : // ======================================================================= void GEOM_Annotation::SetPosition( const gp_Pnt& thePosition ) +{ + SetPosition( thePosition, Standard_True ); +} + +// ======================================================================= +// function : SetPosition +// purpose : +// ======================================================================= +void GEOM_Annotation::SetPosition( const gp_Pnt& thePosition, const Standard_Boolean theUpdateSelection ) { myPosition = thePosition; - UpdatePersistence(); + Handle(Graphic3d_TransformPers) aPersistence; + if ( !myIsScreenFixed ) + { + AIS_InteractiveObject::SetTransformPersistence( Graphic3d_TMF_ZoomPers | Graphic3d_TMF_RotatePers, thePosition ); + } + + SetToUpdate(); + + if( theUpdateSelection ) + { + UpdateSelection(); + } } // ======================================================================= @@ -108,7 +135,20 @@ void GEOM_Annotation::SetScreenFixed( const Standard_Boolean theIsFixed ) { myIsScreenFixed = theIsFixed; - UpdatePersistence(); + if (!myIsScreenFixed) + { + AIS_InteractiveObject::SetTransformPersistence( Graphic3d_TMF_ZoomPers | Graphic3d_TMF_RotatePers, myPosition ); + } + else + { + AIS_InteractiveObject::SetTransformPersistence( Graphic3d_TMF_2d ); + } + + SetZLayer( myIsScreenFixed ? Graphic3d_ZLayerId_Topmost : Graphic3d_ZLayerId_Top ); + + SetToUpdate(); + + UpdateSelection(); } // ======================================================================= @@ -148,6 +188,7 @@ void GEOM_Annotation::SetTextColor( const Quantity_Color& theColor ) void GEOM_Annotation::SetLineColor( const Quantity_Color& theColor ) { myDrawer->LineAspect()->SetColor( theColor ); + myDrawer->PointAspect()->SetColor( theColor ); SetToUpdate(); } @@ -222,22 +263,6 @@ void GEOM_Annotation::SetLineStyle( const Aspect_TypeOfLine theStyle ) } } -// ======================================================================= -// function : UpdatePersistence -// purpose : -// ======================================================================= -void GEOM_Annotation::UpdatePersistence() -{ - if (!myIsScreenFixed) - { - AIS_InteractiveObject::SetTransformPersistence( Graphic3d_TMF_ZoomPers | Graphic3d_TMF_RotatePers, myPosition ); - } - else - { - AIS_InteractiveObject::SetTransformPersistence( Graphic3d_TMF_2d, gp_Pnt( 0.0, 0.0, 0.0 ) ); - } -} - // ======================================================================= // function : Compute // purpose : @@ -267,10 +292,18 @@ void GEOM_Annotation::Compute( const Handle(PrsMgr_PresentationManager3d)& /*the aGroup->AddElement( aAnnotationDraw ); aGroup->SetGroupPrimitivesAspect( myDrawer->TextAspect()->Aspect() ); aGroup->SetGroupPrimitivesAspect( myDrawer->LineAspect()->Aspect() ); + aGroup->SetGroupPrimitivesAspect( myDrawer->PointAspect()->Aspect() ); + + Bnd_Box aBox = TextBoundingBox(); + if ( myIsScreenFixed ) + { + gp_Trsf aOffset2d; + aOffset2d.SetTranslation( gp_Vec( myPosition.X(), myPosition.Y(), 0.0 ) ); + aBox = aBox.Transformed( aOffset2d ); + } - const NCollection_Handle aBoundingBox = TextBoundingBox(); - const gp_Pnt aBoxMin = aBoundingBox->CornerMin(); - const gp_Pnt aBoxMax = aBoundingBox->CornerMax(); + const gp_Pnt aBoxMin = aBox.CornerMin(); + const gp_Pnt aBoxMax = aBox.CornerMax(); aGroup->ChangeBoundingBox() = Graphic3d_BndBox4f ( Graphic3d_Vec4( static_cast( aBoxMin.X() ), static_cast( aBoxMin.Y() ), @@ -287,16 +320,23 @@ void GEOM_Annotation::Compute( const Handle(PrsMgr_PresentationManager3d)& /*the void GEOM_Annotation::ComputeSelection( const Handle(SelectMgr_Selection)& theSelection, const Standard_Integer theMode ) { - if (theMode != 0) + if (theMode != GlobalSelectionMode()) { return; } theSelection->Clear(); - const NCollection_Handle aBoundingBox = TextBoundingBox(); - const Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner( this, 10 ); - const Handle(Select3D_SensitiveBox) aSensitive = new Select3D_SensitiveBox( anEntityOwner, *aBoundingBox.get() ); + Bnd_Box aBox = TextBoundingBox(); + if ( myIsScreenFixed ) + { + gp_Trsf aOffset2d; + aOffset2d.SetTranslation( gp_Vec( myPosition.X(), myPosition.Y(), 0.0 ) ); + aBox = aBox.Transformed( aOffset2d ); + } + + const Handle(GEOM_AnnotationOwner) anEntityOwner = new GEOM_AnnotationOwner( this, 10 ); + const Handle(Select3D_SensitiveBox) aSensitive = new Select3D_SensitiveBox( anEntityOwner, aBox ); theSelection->Add( aSensitive ); } @@ -304,10 +344,9 @@ void GEOM_Annotation::ComputeSelection( const Handle(SelectMgr_Selection)& theSe // function : TextBoundingBox // purpose : // ======================================================================= -NCollection_Handle GEOM_Annotation::TextBoundingBox() const +Bnd_Box GEOM_Annotation::TextBoundingBox() const { Handle(Prs3d_TextAspect) anAsp = myDrawer->TextAspect(); - Bnd_Box aBox; Font_FTFont aFont; unsigned int aResolution = GetContext()->CurrentViewer()->DefaultRenderingParams().Resolution; if ( aFont.Init( anAsp->Aspect()->Font().ToCString(), @@ -317,13 +356,66 @@ NCollection_Handle GEOM_Annotation::TextBoundingBox() const { const NCollection_String aText( (Standard_Utf16Char* )myText.ToExtString() ); const Font_Rect aFontRect = aFont.BoundingBox( aText, Graphic3d_HTA_LEFT, Graphic3d_VTA_BOTTOM ); - NCollection_Handle aBox = new Bnd_Box(); - aBox->Add( gp_Pnt( 0.0, 0.0, 0.0 ) ); - aBox->Add( gp_Pnt( aFontRect.Width(), aFontRect.Height(), 0.0 ) ); + Bnd_Box aBox; + aBox.Add( gp_Pnt( 0.0, 0.0, 0.0 ) ); + aBox.Add( gp_Pnt( aFontRect.Width(), aFontRect.Height(), 0.0 ) ); return aBox; } - return NCollection_Handle(); + return Bnd_Box(); +} + +// ======================================================================= +// function : BeginDrag +// purpose : +// ======================================================================= +void GEOM_Annotation::BeginDrag() +{ + myStartPosition = myPosition; +} + +// ======================================================================= +// function : Drag +// purpose : +// ======================================================================= +void GEOM_Annotation::Drag( const Standard_Integer theDx, + const Standard_Integer theDy, + const Handle(V3d_View)& theView ) +{ + if (myIsScreenFixed) + { + SetPosition( myStartPosition.Translated( gp_Vec( theDx, theDy, 0.0 ) ), Standard_False ); + } + else + { + Standard_Integer aWidth, aHeight; + theView->Window()->Size( aWidth, aHeight ); + gp_Pnt aNormalized = theView->Camera()->Project( myStartPosition ); + gp_Pnt aNormalizedDrag = + aNormalized.Translated( gp_Vec( static_cast(theDx) * 2.0 / aWidth, + static_cast(theDy) * 2.0 / aHeight, + 0.0 ) ); + + SetPosition( theView->Camera()->UnProject( aNormalizedDrag ), Standard_False ); + } +} + +// ======================================================================= +// function : EndDrag +// purpose : +// ======================================================================= +void GEOM_Annotation::EndDrag() +{ + UpdateSelection(); +} + +// ======================================================================= +// function : UndoDrag +// purpose : +// ======================================================================= +void GEOM_Annotation::UndoDrag() +{ + SetPosition( myStartPosition, Standard_True ); } // ======================================================================= @@ -404,21 +496,25 @@ void GEOM_Annotation::OpenGl_Annotation::Render( const Handle(OpenGl_Workspace)& // --------------------------------------------------------------------- // initialize text's font and configure some properties when DPI changes // --------------------------------------------------------------------- + const unsigned int aDPI = theWorkspace->View()->RenderingParams().Resolution; if (myTextDPI != aDPI) { const OpenGl_AspectText* anAspect = theWorkspace->AspectText(); // getting string size will also initialize font library - Standard_ShortReal aWidth, aHeight, aDescent; - myTextDraw->StringSize( aContext, myText, *anAspect, myTextParams, aDPI, aWidth, aHeight, aDescent ); + myTextDraw->StringSize( aContext, + myText, *anAspect, myTextParams, aDPI, + myTextSize.x(), myTextSize.y(), myTextSize.z() ); + myTextDPI = aDPI; - myTextLineY = ceil( aHeight * -0.2f ); + myTextUnderline.x() = 0.f; + myTextUnderline.y() = ceil( myTextSize.y() * -0.2f ); Handle(Graphic3d_ArrayOfSegments) aVertexArray = new Graphic3d_ArrayOfSegments( 2 ); - aVertexArray->AddVertex( 0.0f, myTextLineY, 0.0f ); - aVertexArray->AddVertex( aWidth, myTextLineY, 0.0f ); + aVertexArray->AddVertex( 0.0f, myTextUnderline.y(), 0.0f ); + aVertexArray->AddVertex( myTextSize.x(), myTextUnderline.y(), 0.0f ); myTextLineDraw->InitBuffers( aContext, Graphic3d_TOPA_SEGMENTS, aVertexArray->Indices(), aVertexArray->Attributes(), aVertexArray->Bounds() ); } @@ -426,6 +522,7 @@ void GEOM_Annotation::OpenGl_Annotation::Render( const Handle(OpenGl_Workspace)& // --------------------------------------------- // perform view culling test by attachment point // --------------------------------------------- + const OpenGl_Vec4 aAttach( static_cast( myAISObject->myAttach.X() ), static_cast( myAISObject->myAttach.Y() ), static_cast( myAISObject->myAttach.Z() ), 1.F ); @@ -437,35 +534,72 @@ void GEOM_Annotation::OpenGl_Annotation::Render( const Handle(OpenGl_Workspace)& if (myAISObject->myIsAutoHide) { const OpenGl_Vec4 aAttachClip = aCameraProjMat * aAttachView; - if (abs( aAttachClip.x() ) > aAttachClip.w() - || abs( aAttachClip.y() ) > aAttachClip.w() - || abs( aAttachClip.z() ) > aAttachClip.w()) + if (Abs( aAttachClip.x() ) > aAttachClip.w() + || Abs( aAttachClip.y() ) > aAttachClip.w() + || Abs( aAttachClip.z() ) > aAttachClip.w()) { return; } } + const bool toHighlight = theWorkspace->ToHighlight(); + + if (toHighlight && myAISObject->myHilightMode == HighlightLabel) + { + theWorkspace->SetHighlight( false ); + theWorkspace->ApplyAspectLine(); + } + // ------------------------------------------------------------- // render text label in current persistence matrix and underline // ------------------------------------------------------------- + + if ( myAISObject->myIsScreenFixed ) + { + myTextDraw->SetPosition( OpenGl_Vec3( static_cast( myAISObject->myPosition.X() ), + static_cast( myAISObject->myPosition.Y() ), + static_cast( myAISObject->myPosition.Z() ) ) ); + } + myTextDraw->Render( theWorkspace ); - // ---------------------------------------------- - // render underline in current persistence matrix - // ---------------------------------------------- - const bool toHighlight = theWorkspace->ToHighlight(); - if (toHighlight && myAISObject->myHilightMode == HighlightLabel) + // ------------------------------------------------------------ + // render annotation text's underline + // ------------------------------------------------------------ + + if ( myAISObject->myIsScreenFixed ) { - theWorkspace->SetHighlight( false ); - theWorkspace->ApplyAspectLine(); + // setup local transformation (in 2D persistence reference) + // to represent position of annotation label on screen + const OpenGl_Mat4& aViewMat = aContext->WorldViewState.Current(); + OpenGl_Mat4 aPositionMat; + aPositionMat.SetValue( 0, 3, static_cast( myAISObject->myPosition.X() ) ); + aPositionMat.SetValue( 1, 3, static_cast( myAISObject->myPosition.Y() ) ); + aPositionMat.SetValue( 2, 3, static_cast( myAISObject->myPosition.Z() ) ); + OpenGl_Mat4 aPosViewMat = aViewMat * aPositionMat; + aContext->WorldViewState.Push(); + aContext->WorldViewState.SetCurrent( aPosViewMat ); + aContext->ApplyModelViewMatrix(); } + myTextLineDraw->Render( theWorkspace ); // ------------------------------------------------------------ // render dynamic extension line using synthetic transformation // ------------------------------------------------------------ + + // compute label's center in view coordinate space const OpenGl_Mat4& aViewMat = aContext->WorldViewState.Current(); - const OpenGl_Vec4 aHingeView = aViewMat * OpenGl_Vec4( 0.0f, myTextLineY, 0.0f, 1.0f ); + const OpenGl_Vec4 aCenterView = + aViewMat * OpenGl_Vec4( myTextSize.x() / 2.0f, myTextSize.y() / 2.0f, 0.0f, 1.0f ); + + // the value below defines whether the extension line should be hanging + // on the left side of the label or on the right + const bool isLeftHanded = aAttachView.x() < aCenterView.x(); + + // compute extension line point at the text label in view coordinate space + const OpenGl_Vec4 aHingeView = aViewMat * OpenGl_Vec4( + ( isLeftHanded ? myTextUnderline.x() : myTextUnderline.x() + myTextSize.x() ), myTextUnderline.y(), 0.0f, 1.0f ); // prepare matrix to specify geometry of extension line in view space // by multiplication of unit z coordinate vector on given matrix. @@ -473,6 +607,7 @@ void GEOM_Annotation::OpenGl_Annotation::Render( const Handle(OpenGl_Workspace)& aExtGeometryMat.SetColumn( 2, aAttachView - aHingeView ); aExtGeometryMat.SetColumn( 3, aHingeView ); + // setup and draw aContext->ModelWorldState.Push(); aContext->ModelWorldState.SetIdentity(); aContext->WorldViewState.Push(); @@ -482,8 +617,18 @@ void GEOM_Annotation::OpenGl_Annotation::Render( const Handle(OpenGl_Workspace)& myExtLineDraw->Render( theWorkspace ); myExtMarkerDraw->Render( theWorkspace ); + // ------------------------------------------------------------ + // restore original state + // ------------------------------------------------------------ + aContext->ModelWorldState.Pop(); aContext->WorldViewState.Pop(); + + if (myAISObject->myIsScreenFixed) + { + aContext->WorldViewState.Pop(); + } + aContext->ApplyModelViewMatrix(); if (toHighlight != theWorkspace->ToHighlight()) @@ -492,3 +637,14 @@ void GEOM_Annotation::OpenGl_Annotation::Render( const Handle(OpenGl_Workspace)& } } +// ======================================================================= +// subclass : GEOM_AnnotationOwner +// function : HilightWithColor +// purpose : Perform highlighting of the presentation. +// ======================================================================= +void GEOM_Annotation::GEOM_AnnotationOwner::HilightWithColor( const Handle(PrsMgr_PresentationManager3d)& thePresentationMgr, + const Quantity_NameOfColor theColor, + const Standard_Integer theMode ) +{ + thePresentationMgr->Color( Selectable(), theColor, theMode, NULL, Selectable()->ZLayer() ); +} diff --git a/src/OBJECT/GEOM_Annotation.hxx b/src/OBJECT/GEOM_Annotation.hxx index ac6b28904..ef7fcc57e 100755 --- a/src/OBJECT/GEOM_Annotation.hxx +++ b/src/OBJECT/GEOM_Annotation.hxx @@ -45,6 +45,7 @@ class OpenGl_GraphicDriver; class OpenGl_PrimitiveArray; class OpenGl_Text; +class V3d_View; /*! * \class GEOM_Annotation @@ -171,9 +172,26 @@ public: //! Returns highlight mode HighlightMode GetHilightMode() const { return myHilightMode; } -private: +// Interactive dragging: +public: + + //! Prepares necessary data to perform dragging. + Standard_EXPORT void BeginDrag(); + + //! Drags annotation presentation in the screen plane using the given pixel delta. + //! \param theDx, theDy [in] the drag offset in pixels (from beginning of dragging). + //! \param theView [in] the current view for evaluating drag with 3D position mode. + Standard_EXPORT void Drag( const Standard_Integer theDx, + const Standard_Integer theDy, + const Handle(V3d_View)& theView ); - void UpdatePersistence(); + //! Perform necessary update when dragging is finished. + Standard_EXPORT void EndDrag(); + + //! Perform necessary update when dragging need undo. + Standard_EXPORT void UndoDrag(); + +private: virtual void Compute( const Handle(PrsMgr_PresentationManager3d)& thePresentationManager, const Handle(Prs3d_Presentation)& thePresentation, @@ -182,17 +200,20 @@ private: virtual void ComputeSelection( const Handle(SelectMgr_Selection)& theSelection, const Standard_Integer theMode ) Standard_OVERRIDE; - virtual void SetLocalTransformation( const gp_Trsf& theTransformation ) Standard_OVERRIDE {} + virtual void SetLocalTransformation( const gp_Trsf& /*theTransformation*/ ) Standard_OVERRIDE {} + + virtual void SetTransformPersistence( const Graphic3d_TransModeFlags& /*theFlag*/, + const gp_Pnt& /*thePoint*/ ) Standard_OVERRIDE {} - virtual void SetTransformPersistence( const Graphic3d_TransModeFlags& theFlag, - const gp_Pnt& thePoint = gp_Pnt (0.0, 0.0, 0.0) ) Standard_OVERRIDE {} + Bnd_Box TextBoundingBox() const; - NCollection_Handle TextBoundingBox() const; + void SetPosition( const gp_Pnt& thePosition, const Standard_Boolean theUpdateSelection ); private: gp_Pnt myAttach; //!< Attachment point of extension line. gp_Pnt myPosition; //!< Position of text label. + gp_Pnt myStartPosition; //!< Position before starting dragging operation. Standard_Boolean myIsScreenFixed; //!< Flag indicating whether "screen fixed" positioning mode is turned on or off. Standard_Boolean myIsAutoHide; //!< Flag indicating whether "auto-hiding" option is turned on. HighlightMode myHilightMode; //!< Highlight mode for presentation. @@ -234,10 +255,34 @@ private: OpenGl_PrimitiveArray* myExtLineDraw; //!< Extension line draw element. OpenGl_PrimitiveArray* myExtMarkerDraw; //!< Extension marker draw element. mutable float myTextLineY; //!< Text's underlines relative position. + mutable Graphic3d_Vec3 myTextSize; //!< Text's width, height and descent. + mutable Graphic3d_Vec2 myTextUnderline; //!< Text's underline position. mutable unsigned int myTextDPI; //!< Text's DPI scale used for last rendering. }; friend class OpenGl_Annotation; // allow opengl element to get private data and invoke callback methods + +private: + + //! Custom entity owner implementing correct highlight for topmost mode. + class GEOM_AnnotationOwner : public SelectMgr_EntityOwner + { + public: + + //! Constructor. + GEOM_AnnotationOwner( const Handle(SelectMgr_SelectableObject)& theSelectable, + const Standard_Integer thePriority = 0 ) + : SelectMgr_EntityOwner( theSelectable, thePriority ) {} + + //! Perform highlighting of the presentation. + //! \param thePresentationMgr [in] the presentation manager. + //! \param theColor [in] the highlighting color. + //! \param theMode [in] the display mode. + virtual void + HilightWithColor( const Handle(PrsMgr_PresentationManager3d)& thePresentationMgr, + const Quantity_NameOfColor theColor, + const Standard_Integer theMode = 0 ) Standard_OVERRIDE; + }; }; DEFINE_STANDARD_HANDLE( GEOM_Annotation, AIS_InteractiveObject ) -- 2.39.2