@@ -22,17 +22,17 @@ void ObjectLabel::setLabel( const PositionedText& label )
2222 if ( label == label_ )
2323 return ;
2424 label_ = label;
25- if ( !pathToFont_. empty () )
26- buildMesh_ ( );
25+ needRebuild_ = true ;
26+ setDirtyFlags ( DIRTY_POSITION | DIRTY_FACE );
2727}
2828
2929void ObjectLabel::setFontPath ( const std::filesystem::path& pathToFont )
3030{
3131 if ( pathToFont_ == pathToFont )
3232 return ;
3333 pathToFont_ = pathToFont;
34- if ( !label_. text . empty () )
35- buildMesh_ ( );
34+ needRebuild_ = true ;
35+ setDirtyFlags ( DIRTY_POSITION | DIRTY_FACE );
3636}
3737
3838void ObjectLabel::setPivotPoint ( const Vector2f& pivotPoint )
@@ -69,47 +69,11 @@ void ObjectLabel::swapBase_( Object& other )
6969
7070Box3f ObjectLabel::computeBoundingBox_ () const
7171{
72- if ( !mesh_ )
73- return {};
7472 Box3f box;
7573 box.include ( label_.position );
7674 return box;
7775}
7876
79- Expected<std::future<void >, std::string> ObjectLabel::serializeModel_ ( const std::filesystem::path& path ) const
80- {
81- if ( ancillary_ || !mesh_ )
82- return {};
83-
84- #ifndef MRMESH_NO_OPENCTM
85- auto save = [mesh = mesh_, filename = utf8string ( path ) + " .ctm" , this ]()
86- {
87- MR::MeshSave::toCtm ( *mesh, pathFromUtf8 ( filename ), {}, vertsColorMap_.empty () ? nullptr : &vertsColorMap_ );
88- };
89- #else
90- auto save = [mesh = mesh_, filename = utf8string ( path ) + " .mrmesh" ]()
91- {
92- MR::MeshSave::toMrmesh ( *mesh, pathFromUtf8 ( filename ) );
93- };
94- #endif
95-
96- return std::async ( getAsyncLaunchType (), save );
97- }
98-
99- VoidOrErrStr ObjectLabel::deserializeModel_ ( const std::filesystem::path& path, ProgressCallback progressCb )
100- {
101- #ifndef MRMESH_NO_OPENCTM
102- auto res = MeshLoad::fromCtm ( pathFromUtf8 ( utf8string ( path ) + " .ctm" ), &vertsColorMap_, progressCb );
103- #else
104- auto res = MeshLoad::fromMrmesh ( pathFromUtf8 ( utf8string ( path ) + " .mrmesh" ), &vertsColorMap_, progressCb );
105- #endif
106- if ( !res.has_value () )
107- return unexpected ( res.error () );
108-
109- mesh_ = std::make_shared<Mesh>( std::move ( res.value () ) );
110- return {};
111- }
112-
11377void ObjectLabel::serializeFields_ ( Json::Value& root ) const
11478{
11579 VisualObject::serializeFields_ ( root );
@@ -120,13 +84,20 @@ void ObjectLabel::serializeFields_( Json::Value& root ) const
12084
12185 root[" PathToFontFile" ] = utf8string ( pathToFont_ );
12286
87+ root[" SourcePoint" ] = sourcePoint_.value ();
88+ root[" Background" ] = background_.value ();
89+ root[" Contour" ] = contour_.value ();
90+ root[" LeaderLine" ] = leaderLine_.value ();
91+
12392 // append base type
12493 root[" Type" ].append ( ObjectLabel::TypeName () );
12594
12695 root[" SourcePointSize" ] = sourcePointSize_;
12796 root[" LeaderLineWidth" ] = leaderLineWidth_;
12897 root[" BackgroundPadding" ] = backgroundPadding_;
12998
99+ serializeToJson ( pivotPoint_, root[" PivotPoint" ] );
100+
130101 serializeToJson ( sourcePointColor_.get (), root[" Colors" ][" SourcePoint" ] );
131102 serializeToJson ( leaderLineColor_.get (), root[" Colors" ][" LeaderLine" ] );
132103 serializeToJson ( contourColor_.get (), root[" Colors" ][" Contour" ] );
@@ -144,22 +115,38 @@ void ObjectLabel::deserializeFields_( const Json::Value& root )
144115 if ( root[" PathToFontFile" ].isString () )
145116 pathToFont_ = root[" PathToFontFile" ].asString ();
146117
118+ if ( root[" SourcePoint" ].isUInt () )
119+ sourcePoint_ = ViewportMask ( root[" SourcePoint" ].asUInt () );
120+ if ( root[" Background" ].isUInt () )
121+ background_ = ViewportMask ( root[" Background" ].asUInt () );
122+ if ( root[" Contour" ].isUInt () )
123+ contour_ = ViewportMask ( root[" Contour" ].asUInt () );
124+ if ( root[" LeaderLine" ].isUInt () )
125+ leaderLine_ = ViewportMask ( root[" LeaderLine" ].asUInt () );
126+
147127 if ( root[" SourcePointSize" ].isDouble () )
148128 sourcePointSize_ = root[" SourcePointSize" ].asFloat ();
149129 if ( root[" LeaderLineWidth" ].isDouble () )
150130 leaderLineWidth_ = root[" LeaderLineWidth" ].asFloat ();
151131 if ( root[" BackgroundPadding" ].isDouble () )
152132 backgroundPadding_ = root[" BackgroundPadding" ].asFloat ();
153133
134+ deserializeFromJson ( root[" PivotPoint" ], pivotPoint_ );
135+
154136 deserializeFromJson ( root[" Colors" ][" SourcePoint" ], sourcePointColor_.get () );
155137 deserializeFromJson ( root[" Colors" ][" LeaderLine" ], leaderLineColor_.get () );
156138 deserializeFromJson ( root[" Colors" ][" Contour" ], contourColor_.get () );
139+
140+ needRebuild_ = true ;
157141}
158142
159143void ObjectLabel::setupRenderObject_ () const
160144{
161145 if ( !renderObj_ )
162146 renderObj_ = createRenderObject<ObjectLabel>( *this );
147+
148+ if ( needRebuild_ && !label_.text .empty () && !pathToFont_.empty () )
149+ buildMesh_ ();
163150}
164151
165152void ObjectLabel::setDefaultColors_ ()
@@ -171,7 +158,7 @@ void ObjectLabel::setDefaultColors_()
171158 setContourColor ( Color::gray () );
172159}
173160
174- void ObjectLabel::buildMesh_ ()
161+ void ObjectLabel::buildMesh_ () const
175162{
176163 std::vector<std::string> splited = split ( label_.text , " \n " );
177164
@@ -192,32 +179,29 @@ void ObjectLabel::buildMesh_()
192179
193180 mesh_->addPart ( mesh );
194181 }
195- setDirtyFlags ( DIRTY_POSITION | DIRTY_FACE );
196182
183+ meshBox_ = mesh_->computeBoundingBox ();
197184 updatePivotShift_ ();
198185
186+ // important to call before bindAllVisualization to avoid recursive calls
187+ needRebuild_ = false ;
188+
199189 // we can always clear cpu model for labels
200190 bindAllVisualization ();
201191 mesh_.reset ();
202192}
203193
204- void ObjectLabel::updatePivotShift_ ()
194+ void ObjectLabel::updatePivotShift_ () const
205195{
206- if ( !mesh_ )
196+ if ( !meshBox_. valid () )
207197 return ;
208- const Box3f box = mesh_->computeBoundingBox ();
209- if ( box.valid () )
210- {
211- Vector3f diagonal = box.max + box.min ; // (box.max - box.min) + box.min * 2 - because box.min != 0
212- pivotShift_.x = pivotPoint_.x * diagonal.x ;
213- pivotShift_.y = pivotPoint_.y * diagonal.y ;
214- }
198+ Vector3f diagonal = meshBox_.max + meshBox_.min ; // (box.max - box.min) + box.min * 2 - because box.min != 0
199+ pivotShift_.x = pivotPoint_.x * diagonal.x ;
200+ pivotShift_.y = pivotPoint_.y * diagonal.y ;
215201}
216202
217203Box3f ObjectLabel::getWorldBox ( ViewportId id ) const
218204{
219- if ( !mesh_ )
220- return {};
221205 Box3f box;
222206 box.include ( worldXf ( id )( label_.position ) );
223207 return box;
0 commit comments