OpenWalnut  1.4.0
WGE2DManipulator.cpp
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #include "WGE2DManipulator.h"
00026 
00027 
00028 WGE2DManipulator::WGE2DManipulator()
00029     : m_positionX( -64.0 ),
00030       m_positionY( 0.0 ),
00031       m_zoom( 1.0 )
00032 {
00033 }
00034 
00035 const char* WGE2DManipulator::className() const
00036 {
00037     return "WGE2DManipulator";
00038 }
00039 
00040 void WGE2DManipulator::setByMatrix( const osg::Matrixd& matrix )
00041 {
00042     m_positionX = matrix.getTrans().x();
00043     m_positionY = matrix.getTrans().y();
00044     m_zoom = 1.0 / matrix.getScale().x();
00045 }
00046 
00047 void WGE2DManipulator::setByInverseMatrix( const osg::Matrixd& matrix )
00048 {
00049     m_positionX = -matrix.getTrans().x();
00050     m_positionY = -matrix.getTrans().y();
00051     m_zoom = matrix.getScale().x();
00052 }
00053 
00054 osg::Matrixd WGE2DManipulator::getMatrix() const
00055 {
00056     return osg::Matrixd::scale( 1.0 / m_zoom, 1.0 / m_zoom, 1.0 ) * osg::Matrixd::translate( m_positionX, m_positionY, 0.0 );
00057 }
00058 
00059 osg::Matrixd WGE2DManipulator::getInverseMatrix() const
00060 {
00061     return osg::Matrixd::translate( -m_positionX, -m_positionY, 0.0 ) * osg::Matrixd::scale( m_zoom, m_zoom, 1.0 );
00062 }
00063 
00064 void WGE2DManipulator::home( const osgGA::GUIEventAdapter& /*ea*/, osgGA::GUIActionAdapter& us ) // NOLINT We can not change the interface of OSG
00065 {
00066     m_positionX = -64.0;
00067     m_positionY = 0.0;
00068     m_zoom = 1.0;
00069 
00070     us.requestRedraw();
00071     flushMouseEventStack();
00072 }
00073 
00074 void WGE2DManipulator::init( const osgGA::GUIEventAdapter& /*ea*/, osgGA::GUIActionAdapter& us ) // NOLINT We can not change the interface of OSG
00075 {
00076     flushMouseEventStack();
00077 
00078     us.requestContinuousUpdate( false );
00079 }
00080 
00081 bool WGE2DManipulator::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us )
00082 {
00083     bool handled;
00084     switch( ea.getEventType() )
00085     {
00086         case( osgGA::GUIEventAdapter::PUSH ):
00087         {
00088             addMouseEvent( ea );
00089             handled = true;
00090             break;
00091         }
00092         case( osgGA::GUIEventAdapter::DRAG ):
00093         {
00094             addMouseEvent( ea );
00095             if( calcMovement() )
00096             {
00097                 us.requestRedraw();
00098             }
00099             handled = true;
00100             break;
00101         }
00102         case( osgGA::GUIEventAdapter::SCROLL ):
00103         {
00104             if( zoom( ea ) )
00105             {
00106                 us.requestRedraw();
00107             }
00108             handled = true;
00109             break;
00110         }
00111         // TODO(cornimueller): Also allow to zoom using +/- keys.
00112         case( osgGA::GUIEventAdapter::KEYDOWN ):
00113         {
00114             if( ea.getKey() == osgGA::GUIEventAdapter::KEY_Space )
00115             {
00116                 home( ea, us );
00117                 handled = true;
00118             }
00119             else
00120             {
00121                 handled = false;
00122             }
00123             break;
00124         }
00125         default:
00126             handled = false;
00127     }
00128 
00129     return handled;
00130 }
00131 
00132 void WGE2DManipulator::getUsage( osg::ApplicationUsage& usage ) const // NOLINT We can not change the interface of OSG
00133 {
00134     usage.addKeyboardMouseBinding( "Space", "Reset the view to home" );
00135 }
00136 
00137 WGE2DManipulator::~WGE2DManipulator()
00138 {
00139 }
00140 
00141 void WGE2DManipulator::flushMouseEventStack()
00142 {
00143     m_ga_t1 = NULL;
00144     m_ga_t0 = NULL;
00145 }
00146 
00147 void WGE2DManipulator::addMouseEvent( const osgGA::GUIEventAdapter& ea )
00148 {
00149     m_ga_t1 = m_ga_t0;
00150     m_ga_t0 = &ea;
00151 }
00152 
00153 bool WGE2DManipulator::calcMovement()
00154 {
00155     bool changed = false;
00156     // return if less then two events have been added.
00157     if( m_ga_t0.valid() && m_ga_t1.valid() )
00158     {
00159         unsigned int buttonMask = m_ga_t0->getButtonMask();
00160         if( buttonMask == osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON
00161             || buttonMask == ( osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON | osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON ) )
00162         {
00163             m_positionX += ( m_ga_t1->getX() - m_ga_t0->getX() ) / m_zoom;
00164             m_positionY += ( m_ga_t1->getY() - m_ga_t0->getY() ) / m_zoom;
00165             changed = true;
00166         }
00167     }
00168 
00169     return changed;
00170 }
00171 
00172 bool WGE2DManipulator::zoom( const osgGA::GUIEventAdapter& ea )
00173 {
00174     bool changed = false;
00175     double zoomDelta;
00176 
00177     switch( ea.getScrollingMotion() )
00178     {
00179         case osgGA::GUIEventAdapter::SCROLL_UP:
00180             zoomDelta = -0.05;
00181             break;
00182         case osgGA::GUIEventAdapter::SCROLL_DOWN:
00183             zoomDelta = 0.05;
00184             break;
00185         case osgGA::GUIEventAdapter::SCROLL_2D:
00186             zoomDelta = -0.05 / 120.0 * ea.getScrollingDeltaY();
00187             break;
00188         // case osgGA::GUIEventAdapter::SCROLL_LEFT:
00189         // case osgGA::GUIEventAdapter::SCROLL_RIGHT:
00190         // case osgGA::GUIEventAdapter::SCROLL_NONE:
00191         default:
00192             // do nothing
00193             zoomDelta = 0.0;
00194     }
00195 
00196     if( zoomDelta != 0.0 )
00197     {
00198         m_zoom *= 1.0 + zoomDelta;
00199         // TODO(cornimueller): Correct m_positionX and m_positionY to zoom into the current
00200         //       mouse position, not into the lower left corner.
00201         changed = true;
00202     }
00203 
00204     return changed;
00205 }