diff --git a/source/MRMesh/MRObjectMeshHolder.cpp b/source/MRMesh/MRObjectMeshHolder.cpp index def9972455d5..7a40fc78205b 100644 --- a/source/MRMesh/MRObjectMeshHolder.cpp +++ b/source/MRMesh/MRObjectMeshHolder.cpp @@ -763,8 +763,22 @@ size_t ObjectMeshHolder::numHandles() const void ObjectMeshHolder::setDirtyFlags( uint32_t mask, bool invalidateCaches ) { - VisualObject::setDirtyFlags( mask, invalidateCaches ); + invalidateMetricsCache( mask ); + setDirtyFlagsFast( mask ); + if ( invalidateCaches && ( mask & DIRTY_POSITION || mask & DIRTY_FACE ) && data_.mesh ) + data_.mesh->invalidateCaches(); +} + +void ObjectMeshHolder::setDirtyFlagsFast( uint32_t mask ) +{ + VisualObject::setDirtyFlags( mask ); + if ( ( mask & DIRTY_POSITION || mask & DIRTY_FACE ) && data_.mesh ) + meshChangedSignal( mask ); +} + +void ObjectMeshHolder::invalidateMetricsCache( uint32_t mask ) +{ if ( mask & DIRTY_FACE ) { numHoles_.reset(); @@ -782,16 +796,6 @@ void ObjectMeshHolder::setDirtyFlags( uint32_t mask, bool invalidateCaches ) selectedArea_.reset(); volume_.reset(); avgEdgeLen_.reset(); - if ( invalidateCaches && data_.mesh ) - data_.mesh->invalidateCaches(); - } - - if ( mask & DIRTY_POSITION || mask & DIRTY_FACE) - { - if ( data_.mesh ) - { - meshChangedSignal( mask ); - } } } diff --git a/source/MRMesh/MRObjectMeshHolder.h b/source/MRMesh/MRObjectMeshHolder.h index 6cb765897ad7..3bf731f2ed02 100644 --- a/source/MRMesh/MRObjectMeshHolder.h +++ b/source/MRMesh/MRObjectMeshHolder.h @@ -64,6 +64,14 @@ class MRMESH_CLASS ObjectMeshHolder : public VisualObject MRMESH_API virtual void setDirtyFlags( uint32_t mask, bool invalidateCaches = true ) override; + /// this is a faster version of setDirtyFlags(), which does not invalidate metrics cache (area, volume, ...); + /// the user is responsible for calling invalidateMetricsCache( mask ) or setDirtyFlags( mask ) at the end of mesh editing; + /// DANGER: all cached values returned until then can be outdated + MRMESH_API virtual void setDirtyFlagsFast( uint32_t mask ); + + /// invalidates same caches with mesh metrics (area, volume, ...) as by setDirtyFlags( mask ) + MRMESH_API virtual void invalidateMetricsCache( uint32_t mask ); + const FaceBitSet& getSelectedFaces() const { return data_.selectedFaces; } MRMESH_API virtual void selectFaces( FaceBitSet newSelection ); /// returns colors of selected triangles diff --git a/source/MRViewer/MRSurfaceManipulationWidget.cpp b/source/MRViewer/MRSurfaceManipulationWidget.cpp index 098b74b2cbb1..af34ee01493e 100644 --- a/source/MRViewer/MRSurfaceManipulationWidget.cpp +++ b/source/MRViewer/MRSurfaceManipulationWidget.cpp @@ -466,6 +466,8 @@ bool SurfaceManipulationWidget::onMouseUp_( Viewer::MouseButton button, int /*mo updateValueChanges_( generalEditingRegion_ ); obj_->setDirtyFlags( DIRTY_POSITION ); } + else + invalidateMetricsCache_(); generalEditingRegion_.clear(); generalEditingRegion_.resize( numV, false ); @@ -598,7 +600,7 @@ void SurfaceManipulationWidget::changeSurface_() params.region = &singleEditingRegion_; params.force = settings_.relaxForce; relax( *obj_->varMesh(), params ); - obj_->setDirtyFlags( DIRTY_POSITION ); + obj_->setDirtyFlagsFast( DIRTY_POSITION ); updateValueChanges_( singleEditingRegion_ ); return; } @@ -610,6 +612,7 @@ void SurfaceManipulationWidget::changeSurface_() normal += mesh.dirDblArea( v ); normal = normal.normalized(); + obj_->varMesh()->invalidateCaches(); auto& points = obj_->varMesh()->points; const float maxShift = settings_.editForce; @@ -634,7 +637,7 @@ void SurfaceManipulationWidget::changeSurface_() generalEditingRegion_ |= singleEditingRegion_; changedRegion_ |= singleEditingRegion_; updateValueChanges_( singleEditingRegion_ ); - obj_->setDirtyFlags( DIRTY_POSITION ); + obj_->setDirtyFlagsFast( DIRTY_POSITION ); } void SurfaceManipulationWidget::updateUVmap_( bool set, bool wholeMesh ) @@ -750,12 +753,23 @@ void SurfaceManipulationWidget::updateRegion_( const Vector2f& mousePos ) singleEditingRegion_ -= unchangeableVerts_; } +void SurfaceManipulationWidget::invalidateMetricsCache_() +{ + // if not-Patch mode and some surface change was done without metrics update + if ( !appendHistoryAction_ && historyAction_ ) + { + assert( settings_.workMode != WorkMode::Patch ); + obj_->invalidateMetricsCache( DIRTY_POSITION ); + } +} + void SurfaceManipulationWidget::abortEdit_() { if ( !mousePressed_ ) return; mousePressed_ = false; removeLastStableObjMesh_(); + invalidateMetricsCache_(); appendHistoryAction_ = false; historyAction_.reset(); generalEditingRegion_.clear(); diff --git a/source/MRViewer/MRSurfaceManipulationWidget.h b/source/MRViewer/MRSurfaceManipulationWidget.h index 184a9ffa78ab..9ed5c56db0d8 100644 --- a/source/MRViewer/MRSurfaceManipulationWidget.h +++ b/source/MRViewer/MRSurfaceManipulationWidget.h @@ -122,6 +122,7 @@ class MRVIEWER_CLASS SurfaceManipulationWidget : void changeSurface_(); void updateUVmap_( bool set, bool wholeMesh = false ); void updateRegion_( const Vector2f& mousePos ); + void invalidateMetricsCache_(); void abortEdit_(); /// Laplacian void laplacianPickVert_( const PointOnFace& pick );