MeshLib C++ Docs
Loading...
Searching...
No Matches
MRObjectTransformWidget.h
Go to the documentation of this file.
1#pragma once
2
5#include "MRMesh/MRMeshFwd.h"
6#include "MRMesh/MRVector3.h"
9#include "MRMesh/MRAxis.h"
10#include <MRMesh/MRObject.h>
11#include <MRMesh/MRColor.h>
12#include "MRMesh/MRSignal.h"
13#include <array>
14#include <functional>
15#include <string>
16
17namespace MR
18{
19
20enum class ControlBit
21{
22 None = 0,
23 RotX = 0x1,
24 RotY = 0x2,
25 RotZ = 0x4,
26 RotMask = RotX | RotY | RotZ,
27 MoveX = 0x8,
28 MoveY = 0x10,
29 MoveZ = 0x20,
32};
34
35// This lambda is called in each frame, and returns transform mode mask for this frame in given viewport
36// if not set, full mask is return
37using TransformModesValidator = std::function<ControlBit( const Vector3f& center, const AffineXf3f& xf, ViewportId )>;
38
39
40// Interface class for ObjectTransformWidget custom visualization
41class MRVIEWER_CLASS ITransformControls
42{
43public:
44 virtual ~ITransformControls() = default;
45
46 // get center of the widget in local space
47 const Vector3f& getCenter() const { return center_; }
48 MRVIEWER_API void setCenter( const Vector3f& center );
49
50 // should return current radius of the widget
51 virtual float getRadius() const { return 1.0f; }
52
53 // should calculates and sets the matrix to set the size in pixels
54 virtual void updateSizeInPixel() {};
55
56 // This lambda is called in each frame, and returns transform mode mask for this frame in given viewport
57 // if not set, full mask is return
58 void setTransformModesValidator( TransformModesValidator validator ) { validator_ = validator; }
59
60 // Enables or disables pick through mode, in this mode controls will be picked even if they are occluded by other objects
61 void setPickThrough( bool on ) { pickThrough_ = on; }
62 bool getPickThrough() const { return pickThrough_; }
63
64 // Returns currently hovered control
65 ControlBit getHoveredControl() const { return hoveredControl_; }
66
67 // Called once on widget created to init internal objects
68 virtual void init( std::shared_ptr<Object> parent ) = 0;
69 // Called right after init and can be called on some internal actions to recreate
70 // objects visualization
71 virtual void update() = 0;
72 // Called for hover checks
73 void hover() { hoveredControl_ = hover_( pickThrough_ ); }
74 // This is called to stop drawing active visualization when modification is stopped
75 void stopModify() { stopModify_(); hover(); }
76
77 // Called each frame for each viewport to update available transformation modes
78 MRVIEWER_API void updateVisualTransformMode( ControlBit showMask, ViewportMask viewportMask, const AffineXf3f& xf );
79
80 // One have to implement these functions to have visualization of translation and rotation
81 virtual void updateTranslation( Axis ax, const Vector3f& startMove, const Vector3f& endMove, ViewportId vpId ) = 0;
82 // xf - widget current xf
83 virtual void updateRotation( Axis ax, const AffineXf3f& xf, float startAngle, float endAngle, ViewportId vpId ) = 0;
84
85 // build-in history action class for change center
87 {
88 public:
89 ChangeCenterAction( const std::string& name, ITransformControls& controls ) :
90 controls_{ controls },
91 name_{ name }{ center_ = controls.getCenter(); }
92
93 virtual std::string name() const override { return name_; }
94
95 virtual void action( HistoryAction::Type ) override
96 {
97 auto center = controls_.getCenter();
98 controls_.setCenter( center_ );
99 center_ = center;
100 }
101
102 [[nodiscard]] virtual size_t heapBytes() const override { return name_.capacity(); }
103
104 private:
105 ITransformControls& controls_;
106 Vector3f center_;
107 std::string name_;
108 };
109protected:
110 // one have to implement this function
111 // it can change internal visualization and return currently hovered control
112 virtual ControlBit hover_( bool pickThrough ) = 0;
113 // one have to implement this function
114 // it can change internal visualization
115 // called when modification is stopped
116 virtual void stopModify_() = 0;
117 // one have to implement this function
118 // it can be called in each frame (each viewport if needed) to update transform mode in different viewports
119 virtual void updateVisualTransformMode_( ControlBit showMask, ViewportMask viewportMask ) = 0;
120private:
121 Vector3f center_;
122
123 ControlBit hoveredControl_{ ControlBit::None };
124 bool pickThrough_{ false };
125 TransformModesValidator validator_;
126};
127
128// Basic implementation of ITransformControls
129class MRVIEWER_CLASS TransformControls : public ITransformControls
130{
131public:
132
133 struct MRVIEWER_CLASS VisualParams
134 {
135 // type of length measurement units
136 enum class SizeType
137 {
138 // metric units of measurement
139 LengthUnit = 0,
140 // pixel units of measurement
141 Pixels
142 };
143 // updates radius and width with given box
144 MRVIEWER_API void update( const Box3f& box );
145 // radius in units of measurement, depending on the typeRadius
146 // negative radius value means that controls are not setup
147 float radius{ -1.0f };
148 // width in units of measurement, depending on the typeRadius
149 // negative width value means that controls are not setup
150 float width{ -1.0f };
151 // sets the type of widget size units (metric length or pixels units)
152 SizeType sizeType = SizeType::LengthUnit;
154 float coneRadiusFactor{ 1.35f };
156 float coneSizeFactor{ 2.2f };
158 float negativeLineExtension{ 1.15f };
160 float positiveLineExtension{ 1.3f };
162 std::array<Color, size_t( Axis::Count )> rotationColors{ Color::red(),Color::green(),Color::blue() };
163 std::array<Color, size_t( Axis::Count )> translationColors{ Color::red(),Color::green(),Color::blue() };
164 Color helperLineColor{ Color::black() };
165 Color activeLineColor{ Color::white() };
166 };
167 MRVIEWER_API void setVisualParams( const VisualParams& params );
168 const VisualParams& getVisualParams() const { return params_; }
169
170 MRVIEWER_API virtual ~TransformControls();
171
172 MRVIEWER_API virtual void init( std::shared_ptr<Object> parent ) override;
173 MRVIEWER_API virtual void update() override;
174
175 virtual float getRadius() const override { return params_.radius; }
176 // get current radius of widget controls
177 // negative value means that controls are not setup
178 MRVIEWER_API void setRadius( float radius );
179 // get current width of widget controls
180 // negative value means that controls are not setup
181 float getWidth() const { return params_.width; }
182 // set width for this widget
183 MRVIEWER_API void setWidth( float width );
184 // sets the type of widget size units ( recalculates the current values into new units of measurement )
185 MRVIEWER_API void setSizeType( VisualParams::SizeType type );
186 // calculates and sets the matrix to set the size in pixels
187 MRVIEWER_API virtual void updateSizeInPixel() override;
188
189 MRVIEWER_API virtual void updateTranslation( Axis ax, const Vector3f& startMove, const Vector3f& endMove, ViewportId vpId ) override;
190 MRVIEWER_API virtual void updateRotation( Axis ax, const AffineXf3f& xf, float startAngle, float endAngle, ViewportId vpId ) override;
191
192 // returns TransformModesValidator by threshold dot value (this value is duty for hiding widget controls that have small projection on screen)
193 MRVIEWER_API static TransformModesValidator ThresholdDotValidator( float thresholdDot );
194private:
195 // forgets specific transform for pixel size (if you need to disable this option)
196 void resetSizeInPixel_();
197
198 MRVIEWER_API virtual ControlBit hover_( bool pickThrough ) override;
199 MRVIEWER_API virtual void stopModify_() override;
200 MRVIEWER_API virtual void updateVisualTransformMode_( ControlBit showMask, ViewportMask viewportMask ) override;
201
202 VisualParams params_;
203
204 // Control objects
205 std::array<std::shared_ptr<ObjectMesh>, size_t( Axis::Count )> translateControls_;
206 std::array<std::shared_ptr<ObjectMesh>, size_t( Axis::Count )> rotateControls_;
207
208 // if active line is visible, other lines are not
209 std::shared_ptr<ObjectLines> activeLine_;
210 std::array<std::shared_ptr<ObjectLines>, size_t( Axis::Count )> translateLines_;
211 std::array<std::shared_ptr<ObjectLines>, size_t( Axis::Count )> rotateLines_;
212
213 std::shared_ptr<ObjectMesh> hoveredObject_;
214 int findHoveredIndex_() const;
215 void setActiveLineFromPoints_( const Contour3f& points );
216};
217
218// Visual widget to modify transform
219// present in scene (ancillary), subscribes to viewer events
220class MRVIEWER_CLASS ObjectTransformWidget : public MultiListener<MouseDownListener, MouseMoveListener, MouseUpListener, PreDrawListener, PostDrawListener>
221{
222public:
223 // Creates transform widget around given box and applies given xf
224 // subscribes to viewer events
225 // controls: class that is responsible for visualization
226 // if controls is empty default TransformControls is used
227 MRVIEWER_API void create( const Box3f& box, const AffineXf3f& xf, std::shared_ptr<ITransformControls> controls = {} );
228 // Removes widget from scene and clears all widget objects
229 // unsubscribes from viewer events
230 MRVIEWER_API void reset();
231
232 // Returns current transform mode mask
233 ControlBit getTransformModeMask( ViewportId id = {} ) const { return transformModeMask_.get( id ); }
234 // Sets transform mode mask (enabling or disabling corresponding widget controls)
235 MRVIEWER_API void setTransformMode( ControlBit mask, ViewportId id = {} );
236
237 // Transform operation applying to object while dragging an axis. This parameter does not apply to active operation.
239 {
240 // object moves along an axis
242 // object inflates or deflates along an axis depending on drag direction (away from center or toward center respectively)
244 // object inflates or deflates along all axes depending on drag direction (away from center or toward center respectively)
246 };
247 // Returns current axis transform mode (translate/scale object while dragging an axis)
248 AxisTransformMode getAxisTransformMode() const { return axisTransformMode_; };
249 // Sets current axis transform mode (translate/scale object while dragging an axis)
250 void setAxisTransformMode( AxisTransformMode mode ) { axisTransformMode_ = mode; };
251
252 // Returns root object of widget
253 std::shared_ptr<Object> getRootObject() const { return controlsRoot_; }
254
255 // Returns controls object, that visualize widget
256 std::shared_ptr<ITransformControls> getControls() const { return controls_; }
257 template<typename T>
258 std::shared_ptr<T> getControlsAs() const { return std::dynamic_pointer_cast< T >( controls_ ); }
259
260 // Changes controls xf (controls will affect object in basis of new xf)
261 // note that rotation is applied around 0 coordinate in world space, so use xfAround to process rotation around user defined center
262 // non-uniform scale will be converted to uniform one based on initial box diagonal
263 MRVIEWER_API void setControlsXf( const AffineXf3f& xf, ViewportId id = {} );
264 MRVIEWER_API AffineXf3f getControlsXf( ViewportId id = {} ) const;
265
266 // Subscribes to object visibility, and behave like its child
267 // if obj argument is null, stop following
268 MRVIEWER_API void followObjVisibility( const std::weak_ptr<Object>& obj );
269
270 // Sets callback that will be called in draw function during scaling with current scale arg
271 void setScaleTooltipCallback( std::function<void( float )> callback ) { scaleTooltipCallback_ = callback; }
272 // Sets callback that will be called in draw function during translation with current shift arg
273 void setTranslateTooltipCallback( std::function<void( float )> callback ) { translateTooltipCallback_ = callback; }
274 // Sets callback that will be called in draw function during rotation with current angle in rad
275 void setRotateTooltipCallback( std::function<void( float )> callback ) { rotateTooltipCallback_ = callback; }
276
277 // Sets callback that will be called when modification of widget stops
278 void setStopModifyCallback( std::function<void()> callback ) { stopModifyCallback_ = callback; }
279 // Sets callback that will be called when modification of widget starts
280 void setStartModifyCallback( std::function<void()> callback ) { startModifyCallback_ = callback; }
281 // Sets callback that will be called when widget gets additive transform
282 void setAddXfCallback( std::function<void( const AffineXf3f& )> callback ) { addXfCallback_ = callback; }
283 // Sets callback that will be called when widget gets additive transform
284 // The callback should return true to approve transform and false to reject it
285 void setApproveXfCallback( std::function<bool( const AffineXf3f& )> callback ) { approveXfCallback_ = callback; }
286
287 // History action for TransformWidget
289 {
290 public:
291 ChangeXfAction( const std::string& name, ObjectTransformWidget& widget ) :
292 widget_{ widget },
293 name_{ name }
294 {
295 if ( widget_.controlsRoot_ )
296 {
297 xf_ = widget_.controlsRoot_->xfsForAllViewports();
298 scaledXf_ = widget_.scaledXf_;
299 }
300 }
301
302 virtual std::string name() const override
303 {
304 return name_;
305 }
306
307 virtual void action( HistoryAction::Type ) override
308 {
309 if ( !widget_.controlsRoot_ )
310 return;
311 auto tmpXf = widget_.controlsRoot_->xfsForAllViewports();
312 widget_.controlsRoot_->setXfsForAllViewports( xf_ );
313 xf_ = tmpXf;
314
315 std::swap( scaledXf_, widget_.scaledXf_ );
316 }
317
318 [[nodiscard]] virtual size_t heapBytes() const override
319 {
320 return name_.capacity();
321 }
322
323 private:
324 ObjectTransformWidget& widget_;
327 std::string name_;
328 };
329private:
330 MRVIEWER_API virtual bool onMouseDown_( MouseButton button, int modifier ) override;
331 MRVIEWER_API virtual bool onMouseUp_( MouseButton button, int modifier ) override;
332 MRVIEWER_API virtual bool onMouseMove_( int mouse_x, int mouse_y ) override;
333 MRVIEWER_API virtual void preDraw_() override;
334 MRVIEWER_API virtual void postDraw_() override;
335
336 void activeMove_( bool press = false );
337
338 void processScaling_( Axis ax, bool press );
339 void processTranslation_( Axis ax, bool press );
340 void processRotation_( Axis ax, bool press );
341
342 void setControlsXf_( const AffineXf3f& xf, bool updateScaled, ViewportId id = {} );
343
344 std::weak_ptr<Object> visibilityParent_;
345
346 // undiformAddXf - for ActiveEditMode::ScalingMode only, to scale widget uniformly
347 void addXf_( const AffineXf3f& addXf );
348 void stopModify_();
349
350 // main object that holds all other controls
351 std::shared_ptr<Object> controlsRoot_;
352 std::shared_ptr<ITransformControls> controls_;
353
354 AxisTransformMode axisTransformMode_{ AxisTranslation };
355
356 enum ActiveEditMode
357 {
358 TranslationMode,
359 ScalingMode,
360 UniformScalingMode,
361 RotationMode,
362 };
363 ActiveEditMode activeEditMode_{ TranslationMode };
364
365 // Initial box diagonal vector (before transformation),
366 // it is needed to correctly convert non-uniform scaling to uniform one and apply it to this widget
367 Vector3f boxDiagonal_;
368 // same as controlsRoot_->xf() but with non uniform scaling applied
369 ViewportProperty<AffineXf3f> scaledXf_;
370 // this is needed for tooltip only
371 float currentScaling_ = 1.0f;
372
373 Vector3f prevScaling_;
374 Vector3f startTranslation_;
375 Vector3f prevTranslation_;
376 float accumShift_ = 0;
377
378 float startAngle_ = 0;
379 float accumAngle_ = 0;
380
381 ViewportProperty<ControlBit> transformModeMask_{ ControlBit::FullMask };
382 bool picked_{ false };
383
384 std::function<void( float )> scaleTooltipCallback_;
385 std::function<void( float )> translateTooltipCallback_;
386 std::function<void( float )> rotateTooltipCallback_;
387
388 std::function<void()> startModifyCallback_;
389 std::function<void()> stopModifyCallback_;
390 std::function<void( const AffineXf3f& )> addXfCallback_;
391 std::function<bool( const AffineXf3f& )> approveXfCallback_;
392 bool approvedChange_ = true; // if controlsRoot_ xf changed without approve, user modification stops
393 boost::signals2::connection xfValidatorConnection_;
394};
395
396}
#define MR_MAKE_FLAG_OPERATORS(T)
Definition MRFlagOperators.h:6
Definition MRHistoryAction.h:12
Type
Definition MRHistoryAction.h:19
Definition MRObjectTransformWidget.h:87
virtual size_t heapBytes() const override
returns the amount of memory this object occupies on heap
Definition MRObjectTransformWidget.h:102
ChangeCenterAction(const std::string &name, ITransformControls &controls)
Definition MRObjectTransformWidget.h:89
virtual std::string name() const override
Definition MRObjectTransformWidget.h:93
virtual void action(HistoryAction::Type) override
This function is called on history action (undo, redo, etc.)
Definition MRObjectTransformWidget.h:95
Definition MRObjectTransformWidget.h:42
virtual void stopModify_()=0
const Vector3f & getCenter() const
Definition MRObjectTransformWidget.h:47
virtual void updateVisualTransformMode_(ControlBit showMask, ViewportMask viewportMask)=0
void hover()
Definition MRObjectTransformWidget.h:73
virtual void updateTranslation(Axis ax, const Vector3f &startMove, const Vector3f &endMove, ViewportId vpId)=0
void stopModify()
Definition MRObjectTransformWidget.h:75
virtual void updateRotation(Axis ax, const AffineXf3f &xf, float startAngle, float endAngle, ViewportId vpId)=0
MRVIEWER_API void updateVisualTransformMode(ControlBit showMask, ViewportMask viewportMask, const AffineXf3f &xf)
ControlBit getHoveredControl() const
Definition MRObjectTransformWidget.h:65
void setPickThrough(bool on)
Definition MRObjectTransformWidget.h:61
bool getPickThrough() const
Definition MRObjectTransformWidget.h:62
virtual void update()=0
void setTransformModesValidator(TransformModesValidator validator)
Definition MRObjectTransformWidget.h:58
virtual ControlBit hover_(bool pickThrough)=0
virtual void init(std::shared_ptr< Object > parent)=0
MRVIEWER_API void setCenter(const Vector3f &center)
virtual void updateSizeInPixel()
Definition MRObjectTransformWidget.h:54
virtual ~ITransformControls()=default
virtual float getRadius() const
Definition MRObjectTransformWidget.h:51
Definition MRObjectTransformWidget.h:289
virtual std::string name() const override
Definition MRObjectTransformWidget.h:302
virtual size_t heapBytes() const override
returns the amount of memory this object occupies on heap
Definition MRObjectTransformWidget.h:318
ChangeXfAction(const std::string &name, ObjectTransformWidget &widget)
Definition MRObjectTransformWidget.h:291
virtual void action(HistoryAction::Type) override
This function is called on history action (undo, redo, etc.)
Definition MRObjectTransformWidget.h:307
Definition MRObjectTransformWidget.h:221
MRVIEWER_API AffineXf3f getControlsXf(ViewportId id={}) const
void setStartModifyCallback(std::function< void()> callback)
Definition MRObjectTransformWidget.h:280
void setAddXfCallback(std::function< void(const AffineXf3f &)> callback)
Definition MRObjectTransformWidget.h:282
void setRotateTooltipCallback(std::function< void(float)> callback)
Definition MRObjectTransformWidget.h:275
AxisTransformMode getAxisTransformMode() const
Definition MRObjectTransformWidget.h:248
void setStopModifyCallback(std::function< void()> callback)
Definition MRObjectTransformWidget.h:278
std::shared_ptr< Object > getRootObject() const
Definition MRObjectTransformWidget.h:253
ControlBit getTransformModeMask(ViewportId id={}) const
Definition MRObjectTransformWidget.h:233
MRVIEWER_API void setControlsXf(const AffineXf3f &xf, ViewportId id={})
MRVIEWER_API void reset()
void setTranslateTooltipCallback(std::function< void(float)> callback)
Definition MRObjectTransformWidget.h:273
MRVIEWER_API void followObjVisibility(const std::weak_ptr< Object > &obj)
AxisTransformMode
Definition MRObjectTransformWidget.h:239
@ AxisScaling
Definition MRObjectTransformWidget.h:243
@ AxisTranslation
Definition MRObjectTransformWidget.h:241
@ UniformScaling
Definition MRObjectTransformWidget.h:245
std::shared_ptr< T > getControlsAs() const
Definition MRObjectTransformWidget.h:258
std::shared_ptr< ITransformControls > getControls() const
Definition MRObjectTransformWidget.h:256
void setAxisTransformMode(AxisTransformMode mode)
Definition MRObjectTransformWidget.h:250
void setApproveXfCallback(std::function< bool(const AffineXf3f &)> callback)
Definition MRObjectTransformWidget.h:285
void setScaleTooltipCallback(std::function< void(float)> callback)
Definition MRObjectTransformWidget.h:271
MRVIEWER_API void create(const Box3f &box, const AffineXf3f &xf, std::shared_ptr< ITransformControls > controls={})
MRVIEWER_API void setTransformMode(ControlBit mask, ViewportId id={})
Definition MRObjectTransformWidget.h:130
virtual MRVIEWER_API void init(std::shared_ptr< Object > parent) override
MRVIEWER_API void setRadius(float radius)
MRVIEWER_API void setVisualParams(const VisualParams &params)
virtual float getRadius() const override
Definition MRObjectTransformWidget.h:175
virtual MRVIEWER_API ~TransformControls()
static MRVIEWER_API TransformModesValidator ThresholdDotValidator(float thresholdDot)
const VisualParams & getVisualParams() const
Definition MRObjectTransformWidget.h:168
virtual MRVIEWER_API void updateSizeInPixel() override
virtual MRVIEWER_API void update() override
MRVIEWER_API void setWidth(float width)
virtual MRVIEWER_API void updateTranslation(Axis ax, const Vector3f &startMove, const Vector3f &endMove, ViewportId vpId) override
MRVIEWER_API void setSizeType(VisualParams::SizeType type)
float getWidth() const
Definition MRObjectTransformWidget.h:181
virtual MRVIEWER_API void updateRotation(Axis ax, const AffineXf3f &xf, float startAngle, float endAngle, ViewportId vpId) override
Definition MRViewportId.h:16
stores mask of viewport unique identifiers
Definition MRViewportId.h:38
Definition MRViewportProperty.h:17
auto width(const Box< V > &box)
returns size along x axis
Definition MRMesh/MRBox.h:247
@ None
special value not to limit path in one slice
Definition MRVoxelPath.h:33
Axis
Definition MRAxis.h:6
MouseButton
Definition MRMouse.h:9
std::function< ControlBit(const Vector3f &center, const AffineXf3f &xf, ViewportId)> TransformModesValidator
Definition MRObjectTransformWidget.h:37
LengthUnit
Definition MRUnits.h:24
ControlBit
Definition MRObjectTransformWidget.h:21
Contour3< float > Contour3f
Definition MRMesh/MRMeshFwd.h:299
Definition MRMesh/MRColor.h:9
Definition MRViewerEventsListener.h:29
Definition MRObjectTransformWidget.h:134
MRVIEWER_API void update(const Box3f &box)
SizeType
Definition MRObjectTransformWidget.h:137