Commit 1089d666 authored by Frédéric Larue's avatar Frédéric Larue

Grabbing mode added to GLViewer, enabling to move objects directly in the 3D view.

Only objects whose DisplayableInterface::isGrabbable() function returns true can be moved that way.
If grabbing is validated, the new transformation is notified to the DisplayableInterface through onUpdatingTransformation() function.
parent 21499f7d
......@@ -1602,6 +1602,190 @@ bool GLViewer::imageOfCurrentDisplay( const GenericUIData *m, QImage &renderResu
}
void GLViewer::enterGrabbingMode( bool translation )
{
if( dof() != DisplayDoF::DISPLAY_DOF_3D )
return;
bool itemsAvailableForGrabbing = false;
for( auto &d : m_Displayables )
if( d.second.displayable->isSelected() && d.second.displayable->isGrabbable() )
{
itemsAvailableForGrabbing = true;
break;
}
if( itemsAvailableForGrabbing )
{
m_IsGrabbingTranslationEnabled = translation;
m_IsGrabbingRotationEnabled = !translation;
m_GrabbingAxisConstraint = -1;
setCursor( QCursor(Qt::CursorShape::SizeAllCursor) );
m_ClickMousePos = m_PrevMousePos = mapFromGlobal( cursor().pos() );
setMouseTracking( true );
}
}
void GLViewer::exitGrabbingMode( bool validateTransformations )
{
for( auto &d : m_Displayables )
if( d.second.displayable->isSelected() && d.second.displayable->isGrabbable() )
{
if( validateTransformations )
d.second.displayable->onUpdatingTransformation( d.second.UserTransform() );
else
{
QMatrix4x4 xf;
d.second.displayable->transformation( xf );
d.second.SetUserTransform( xf );
}
}
m_IsGrabbingTranslationEnabled = m_IsGrabbingRotationEnabled = false;
setCursor( QCursor(Qt::ArrowCursor) );
setMouseTracking( false );
update();
}
void GLViewer::onGrabbing( QMouseEvent *evt )
{
#if 0
double dx = evt->pos().x() - m_PrevMousePos.x();
double dy = evt->pos().y() - m_PrevMousePos.y();
QVector3D constraintAxis( 0.0f, 0.0f, 0.0f );
if( m_GrabbingAxisConstraint >= 0 )
constraintAxis[m_GrabbingAxisConstraint] = 1.0f;
QMatrix4x4 xf;
if( m_IsGrabbingTranslationEnabled )
{
double translationScale = 2.0 / (width()*projectionMatrix()(0,0));
if( !isProjectionOrthographic() )
translationScale *= distToFocusPoint();
dx *= translationScale;
dy *= translationScale;
if( m_GrabbingAxisConstraint < 0 )
xf.translate( dx*viewRotationMatrix().row(0).toVector3D() - dy*viewRotationMatrix().row(1).toVector3D() );
else
xf.translate( (dx-dy)*constraintAxis );
}
else //if( m_IsGrabbingRotationEnabled )
{
Box3f selectionBox;
for( auto &d : m_Displayables )
if( d.second.displayable->isSelected() && d.second.displayable->isGrabbable() )
for( auto c : d.second.boundingBox.Corners() )
selectionBox.Add( d.second.UserTransform().map(c) );
xf.translate( selectionBox.Center() );
if( m_GrabbingAxisConstraint < 0 )
xf.rotate( 0.5*dx, frontAxis() );
else
xf.rotate( 0.5*dx, constraintAxis );
xf.translate( -selectionBox.Center() );
}
for( auto &d : m_Displayables )
if( d.second.displayable->isSelected() && d.second.displayable->isGrabbable() )
d.second.SetUserTransform( xf * d.second.UserTransform() );
m_PrevMousePos = evt->pos();
update();
#else
double dx, dy, dt;
QVector3D constraintAxis( 0.0f, 0.0f, 0.0f );
if( m_GrabbingAxisConstraint >= 0 )
constraintAxis[m_GrabbingAxisConstraint] = 1.0f;
QMatrix4x4 xf;
if( m_IsGrabbingTranslationEnabled )
{
double translationScale = 2.0 / (width()*projectionMatrix()(0,0));
if( !isProjectionOrthographic() )
translationScale *= distToFocusPoint();
if( evt->modifiers() & Qt::ControlModifier )
{
double viewScale1 = m_View.metricGrid3D.currentSpacing();
double viewScale2 = viewScale1;
if( evt->modifiers() & Qt::ShiftModifier )
viewScale2 *= 0.1;
double ddx1 = int( translationScale*(m_PrevMousePos.x() - m_ClickMousePos.x()) / viewScale1 );
double ddy1 = int( translationScale*(m_PrevMousePos.y() - m_ClickMousePos.y()) / viewScale1 );
double ddt1 = int( translationScale*(m_PrevMousePos.x() - m_ClickMousePos.x() - m_PrevMousePos.y() + m_ClickMousePos.y()) / viewScale1 );
double ddx2 = int( translationScale*(evt->pos().x() - m_ClickMousePos.x()) / viewScale1 );
double ddy2 = int( translationScale*(evt->pos().y() - m_ClickMousePos.y()) / viewScale1 );
double ddt2 = int( translationScale*(evt->pos().x() - m_ClickMousePos.x() - evt->pos().y() + m_ClickMousePos.y()) / viewScale1 );
dx = (ddx1 != ddx2)? viewScale2*(ddx2-ddx1) : 0.0;
dy = (ddy1 != ddy2)? viewScale2*(ddy2-ddy1) : 0.0;
dt = (ddt1 != ddt2)? viewScale2*(ddt2-ddt1) : 0.0;
}
else
{
dx = translationScale * (evt->pos().x() - m_PrevMousePos.x());
dy = translationScale * (evt->pos().y() - m_PrevMousePos.y());
dt = dx - dy;
}
if( m_GrabbingAxisConstraint < 0 )
xf.translate( dx*viewRotationMatrix().row(0).toVector3D() - dy*viewRotationMatrix().row(1).toVector3D() );
else
xf.translate( dt*constraintAxis );
}
else //if( m_IsGrabbingRotationEnabled )
{
if( evt->modifiers() & Qt::ControlModifier )
{
double rotationScale1 = 15.0;
double rotationScale2 = rotationScale1;
if( evt->modifiers() & Qt::ShiftModifier )
rotationScale2 = 1.0;
double ddx1 = int( 0.5*(m_PrevMousePos.x() - m_ClickMousePos.x()) / rotationScale1 );
double ddx2 = int( 0.5*(evt->pos().x() - m_ClickMousePos.x()) / rotationScale1 );
dx = (ddx1 != ddx2)? rotationScale2*(ddx2-ddx1) : 0.0;
}
else
{
dx = 0.5*(evt->pos().x() - m_PrevMousePos.x());
}
Box3f selectionBox;
for( auto &d : m_Displayables )
if( d.second.displayable->isSelected() && d.second.displayable->isGrabbable() )
for( auto c : d.second.boundingBox.Corners() )
selectionBox.Add( d.second.UserTransform().map(c) );
xf.translate( selectionBox.Center() );
if( m_GrabbingAxisConstraint < 0 )
xf.rotate( dx, frontAxis() );
else
xf.rotate( dx, constraintAxis );
xf.translate( -selectionBox.Center() );
}
for( auto &d : m_Displayables )
if( d.second.displayable->isSelected() && d.second.displayable->isGrabbable() )
d.second.SetUserTransform( xf * d.second.UserTransform() );
m_PrevMousePos = evt->pos();
update();
#endif
}
void GLViewer::enterEvent( QEvent* evt )
{
setFocus();
......@@ -1621,6 +1805,14 @@ void GLViewer::leaveEvent( QEvent* evt )
void GLViewer::mousePressEvent( QMouseEvent *evt )
{
if( isGrabbingEnabled() )
{
if( evt->button() == Qt::RightButton || evt->button() == Qt::LeftButton )
exitGrabbingMode( evt->button() == Qt::LeftButton );
return;
}
if( dof() == DISPLAY_DOF_2D )
{
PickedPoint p;
......@@ -1759,6 +1951,8 @@ void GLViewer::mouseMoveEvent( QMouseEvent *evt )
navigationControl()->mouseMoveEvent( dx, dy, evt );
}
else if( isGrabbingEnabled() )
onGrabbing( evt );
else if( evt->modifiers() & Qt::ShiftModifier )//if( !isSelectionEnabled() )
findObjectUnderCursor( evt->pos() );
}
......@@ -1826,7 +2020,7 @@ void GLViewer::mouseDoubleClickEvent( QMouseEvent *evt )
bool GLViewer::event( QEvent *evt )
{
if( evt->type() == QEvent::KeyPress )
if( evt->type() == QEvent::KeyPress && !isGrabbingEnabled() )
{
QKeyEvent *kevt = static_cast<QKeyEvent*>( evt );
if( kevt->key() == Qt::Key_Tab )
......@@ -1886,7 +2080,7 @@ bool GLViewer::event( QEvent *evt )
}
}
else if( evt->type() == QEvent::KeyRelease )
else if( evt->type() == QEvent::KeyRelease && !isGrabbingEnabled() )
{
QKeyEvent *kevt = static_cast<QKeyEvent*>( evt );
if( kevt->key() == Qt::Key_Shift && !isSelectionEnabled() )
......@@ -1903,6 +2097,29 @@ bool GLViewer::event( QEvent *evt )
void GLViewer::keyPressEvent( QKeyEvent *evt )
{
if( isGrabbingEnabled() )
{
switch( evt->key() )
{
case Qt::Key_Return:
case Qt::Key_Enter:
case Qt::Key_Escape: exitGrabbingMode( evt->key() != Qt::Key_Escape ); break;
case Qt::Key_X:
case Qt::Key_Y:
case Qt::Key_Z:
{
resetGrabbingMode();
int axis = evt->key() - Qt::Key_X;
m_GrabbingAxisConstraint = (m_GrabbingAxisConstraint==axis)? -1 : axis;
break;
}
}
return;
}
if( navigationControl()->keyPressEvent(evt) )
return;
......@@ -1952,16 +2169,10 @@ void GLViewer::keyPressEvent( QKeyEvent *evt )
update();
break;
}
case Qt::Key_Plus:
{
increasePointSize();
break;
}
case Qt::Key_Minus:
{
decreasePointSize();
break;
}
case Qt::Key_Plus : increasePointSize(); break;
case Qt::Key_Minus: decreasePointSize(); break;
case Qt::Key_T:
case Qt::Key_R: enterGrabbingMode( evt->key() == Qt::Key_T ); break;
default: defaultBehaviour = true;
}
}
......
......@@ -98,6 +98,7 @@ protected:
UIParamSet &params );
inline void SetUserTransform( const QMatrix4x4& tr ) { userTransform = tr; fullTransform = tr * packingTransform; }
inline const QMatrix4x4& UserTransform() const { return userTransform; }
inline void SetPackingTransform( const QMatrix4x4& tr ) { packingTransform = tr; fullTransform = userTransform * tr; }
inline const QMatrix4x4& GetTransform() const { return fullTransform; }
......@@ -222,6 +223,15 @@ protected:
bool m_IsCursorInside;
bool m_IsGrabbingTranslationEnabled = false;
bool m_IsGrabbingRotationEnabled = false;
int m_GrabbingAxisConstraint = -1;
void enterGrabbingMode( bool translation );
void exitGrabbingMode( bool validateTransformations );
inline void resetGrabbingMode() { bool tr = m_IsGrabbingTranslationEnabled; exitGrabbingMode(false); enterGrabbingMode(tr); }
void onGrabbing( QMouseEvent *evt );
inline bool isGrabbingEnabled() const { return m_IsGrabbingTranslationEnabled || m_IsGrabbingRotationEnabled; }
/*****************************\
| Constructor(s) / destructor |
\*****************************/
......
......@@ -160,6 +160,11 @@ public:
/** Apply a functor to every selected entity. */
virtual void processSelection( SelectionManager *mngr, BaseSelectionProcessor &proc ) {}
/** Specify if this item can be grabbed and moved in the 3D viewer. */
virtual bool isGrabbable() const { return false; }
/** Function called when the item grabbing motion has been validated in the 3D viewer. */
virtual void onUpdatingTransformation( const QMatrix4x4 &tr ) {}
signals:
void registerAnimation( DisplayableInterface *d );
void unregisterAnimation( DisplayableInterface *d );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment