00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <iostream>
00026 #include <string>
00027
00028 #include <osg/Vec3>
00029
00030 #include "../common/math/linearAlgebra/WLinearAlgebra.h"
00031
00032 #include "WPickHandler.h"
00033 #include "WPickInfo.h"
00034
00035 WPickHandler::WPickHandler()
00036 : m_hitResult( WPickInfo() ),
00037 m_startPick( WPickInfo() ),
00038 m_shift( false ),
00039 m_ctrl( false ),
00040 m_viewerName( "" ),
00041 m_paintMode( 0 ),
00042 m_mouseButton( WPickInfo::NOMOUSE )
00043 {
00044 }
00045
00046 WPickHandler::WPickHandler( std::string viewerName )
00047 : m_hitResult( WPickInfo() ),
00048 m_startPick( WPickInfo() ),
00049 m_shift( false ),
00050 m_ctrl( false ),
00051 m_viewerName( viewerName ),
00052 m_paintMode( 0 ),
00053 m_mouseButton( WPickInfo::NOMOUSE )
00054 {
00055 }
00056
00057 WPickHandler::~WPickHandler()
00058 {
00059 }
00060
00061 WPickInfo WPickHandler::getHitResult()
00062 {
00063 return m_hitResult;
00064 }
00065
00066 boost::signals2::signal1< void, WPickInfo >* WPickHandler::getPickSignal()
00067 {
00068 return &m_pickSignal;
00069 }
00070
00071 bool WPickHandler::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa )
00072 {
00073 switch ( ea.getEventType() )
00074 {
00075 case osgGA::GUIEventAdapter::DRAG :
00076 case osgGA::GUIEventAdapter::PUSH :
00077 {
00078 unsigned int buttonMask = ea.getButtonMask();
00079 if( buttonMask == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON )
00080 {
00081 m_mouseButton = WPickInfo::MOUSE_RIGHT;
00082 osgViewer::View* view = static_cast< osgViewer::View* >( &aa );
00083 if( view )
00084 {
00085 pick( view, ea );
00086 }
00087 }
00088 if( ( buttonMask == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON ) && ( m_paintMode == 1 ) )
00089 {
00090 m_mouseButton = WPickInfo::MOUSE_LEFT;
00091 osgViewer::View* view = static_cast< osgViewer::View* >( &aa );
00092 if( view )
00093 {
00094 pick( view, ea );
00095 }
00096 }
00097 return false;
00098 }
00099 case osgGA::GUIEventAdapter::RELEASE :
00100 {
00101 m_mouseButton = WPickInfo::NOMOUSE;
00102 osgViewer::View* view = static_cast< osgViewer::View* >( &aa );
00103 if( view )
00104 {
00105 unpick();
00106 }
00107 return false;
00108 }
00109 case osgGA::GUIEventAdapter::KEYUP :
00110 {
00111 m_shift = false;
00112 m_ctrl = false;
00113 return false;
00114 }
00115 case osgGA::GUIEventAdapter::KEYDOWN :
00116 {
00117 if( ea.getKey() == 'c' )
00118 {
00119 osgViewer::View* view = static_cast< osgViewer::View* >( &aa );
00120 osg::ref_ptr< osgGA::GUIEventAdapter > event = new osgGA::GUIEventAdapter( ea );
00121 event->setX( ( ea.getXmin() + ea.getXmax() ) * 0.5 );
00122 event->setY( ( ea.getYmin() + ea.getYmax() ) * 0.5 );
00123 if( view )
00124 {
00125 pick( view, *event );
00126 }
00127 }
00128 if( ea.getKey() == osgGA::GUIEventAdapter::KEY_Shift_L )
00129 {
00130 m_shift = true;
00131 }
00132 if( ea.getKey() == osgGA::GUIEventAdapter::KEY_Control_L || ea.getKey() == osgGA::GUIEventAdapter::KEY_Control_R )
00133 {
00134 m_ctrl = true;
00135 }
00136 return false;
00137 }
00138 default:
00139 return false;
00140 }
00141 }
00142
00143 void WPickHandler::unpick( )
00144 {
00145 if( m_hitResult != WPickInfo() )
00146 {
00147 m_hitResult = WPickInfo( "unpick", m_viewerName, WPosition(), std::make_pair( 0, 0 ), WPickInfo::NONE );
00148 m_startPick = WPickInfo();
00149 }
00150 m_pickSignal( getHitResult() );
00151 }
00152
00153 std::string extractSuitableName( osgUtil::LineSegmentIntersector::Intersections::iterator hitr )
00154 {
00155 if( !hitr->nodePath.empty() && !( hitr->nodePath.back()->getName().empty() ) )
00156 {
00157 return hitr->nodePath.back()->getName();
00158 }
00159 else if( hitr->drawable.valid() )
00160 {
00161 return hitr->drawable->className();
00162 }
00163 assert( 0 && "This should not happen. Tell \"wiebel\" if it does." );
00164 return "";
00165 }
00166
00167 void WPickHandler::updatePickInfoModifierKeys( WPickInfo* pickInfo )
00168 {
00169 if( m_shift )
00170 {
00171 pickInfo->setModifierKey( WPickInfo::SHIFT );
00172 }
00173
00174 if( m_ctrl )
00175 {
00176 pickInfo->setModifierKey( WPickInfo::STRG );
00177 }
00178 }
00179
00180 void WPickHandler::pick( osgViewer::View* view, const osgGA::GUIEventAdapter& ea )
00181 {
00182 osgUtil::LineSegmentIntersector::Intersections intersections;
00183 m_hitResult = WPickInfo();
00184 float x = ea.getX();
00185 float y = ea.getY();
00186
00187 WPickInfo pickInfo;
00188
00189 updatePickInfoModifierKeys( &pickInfo );
00190
00191
00192 if( m_viewerName != "" && m_viewerName != "main" )
00193 {
00194 pickInfo = WPickInfo( "", m_viewerName, m_startPick.getPickPosition(), std::make_pair( x, y ),
00195 m_startPick.getModifierKey(), m_mouseButton, m_startPick.getPickNormal() );
00196 m_hitResult = pickInfo;
00197
00198
00199 m_startPick = pickInfo;
00200
00201 m_pickSignal( getHitResult() );
00202
00203 return;
00204 }
00205
00206 bool intersetionsExist = view->computeIntersections( x, y, intersections );
00207
00208
00209 bool startPickIsStillInList = false;
00210 osgUtil::LineSegmentIntersector::Intersections::iterator hitr;
00211 if( intersetionsExist )
00212 {
00213 assert( intersections.size() );
00214 hitr = intersections.begin();
00215
00216 bool ignoreFirst = m_ctrl;
00217
00218 while( hitr != intersections.end() )
00219 {
00220 std::string nodeName = extractSuitableName( hitr );
00221
00222 if( nodeName[0] == '_' && ( m_paintMode == 0 ) )
00223 {
00224 ++hitr;
00225 }
00226
00227 else if( ignoreFirst )
00228 {
00229 ++hitr;
00230 ignoreFirst = false;
00231 }
00232 else
00233 {
00234 break;
00235 }
00236 }
00237
00238 if( hitr == intersections.end() )
00239 {
00240
00241
00242 if( m_startPick.getName() == "" )
00243 {
00244 return;
00245 }
00246 }
00247
00248
00249 if( m_startPick.getName() != "" && m_startPick.getName() != "unpick" )
00250 {
00251 while( ( hitr != intersections.end() ) && !startPickIsStillInList )
00252 {
00253 WPickInfo pickInfoTmp( extractSuitableName( hitr ), m_viewerName, WPosition(), std::make_pair( 0, 0 ), WPickInfo::NONE );
00254 startPickIsStillInList |= ( pickInfoTmp.getName() == m_startPick.getName() );
00255
00256 if( !startPickIsStillInList )
00257 {
00258 ++hitr;
00259 }
00260 }
00261 }
00262 }
00263 else
00264 {
00265
00266
00267
00268 if( m_startPick.getName() == "" )
00269 {
00270 pickInfo = WPickInfo( "nothing", m_viewerName, WPosition( 0.0, 0.0, 0.0 ), std::make_pair( x, y ),
00271 m_startPick.getModifierKey(), m_mouseButton, WVector3d( 0.0, 0.0, 0.0 ) );
00272
00273 m_hitResult = pickInfo;
00274 m_pickSignal( getHitResult() );
00275 return;
00276 }
00277 }
00278
00279
00280 if( startPickIsStillInList || ( intersetionsExist && ( m_startPick.getName() == "unpick" || m_startPick.getName() == "" ) ) )
00281 {
00282
00283 WPosition pickPos;
00284 pickPos[0] = hitr->getWorldIntersectPoint()[0];
00285 pickPos[1] = hitr->getWorldIntersectPoint()[1];
00286 pickPos[2] = hitr->getWorldIntersectPoint()[2];
00287
00288 WVector3d pickNormal;
00289 pickNormal[0] = hitr->getWorldIntersectNormal()[0];
00290 pickNormal[1] = hitr->getWorldIntersectNormal()[1];
00291 pickNormal[2] = hitr->getWorldIntersectNormal()[2];
00292 pickInfo = WPickInfo( extractSuitableName( hitr ), m_viewerName, pickPos, std::make_pair( x, y ),
00293 pickInfo.getModifierKey(), m_mouseButton, pickNormal );
00294 }
00295
00296
00297 if( !startPickIsStillInList && m_startPick.getName() != "" && m_startPick.getName() != "unpick" )
00298 {
00299 pickInfo = WPickInfo( m_startPick.getName(), m_viewerName, m_startPick.getPickPosition(), std::make_pair( x, y ),
00300 m_startPick.getModifierKey(), m_mouseButton, m_startPick.getPickNormal() );
00301 }
00302
00303 m_hitResult = pickInfo;
00304
00305
00306 m_startPick = pickInfo;
00307
00308 m_pickSignal( getHitResult() );
00309 }
00310
00311 void WPickHandler::setPaintMode( int mode )
00312 {
00313 m_paintMode = mode;
00314 }