Main Page | Namespace List | Class Hierarchy | Class List | File List | Class Members | File Members

src/UserInterface.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 Traplas visualisation.
00004 
00005 Copyright (C) 2006 Herbert de Vos & Willem Drost
00006 
00007 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
00010 
00011 You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00012 
00013 */
00014 
00015 
00016 //osg headers for nodes, etc
00017 //
00018 
00019 #ifndef STATECONTROL_H
00020 #include "StateControl.h"
00021 #endif
00022 
00023 #ifndef USERINTERFACE_H
00024 #include "UserInterface.h"
00025 #endif
00026 
00027 #ifndef GLOBALS_H
00028 #include "Globals.h"
00029 #endif
00030 
00031 #ifndef _GLIBCXX_SSTREAM
00032 #include <sstream>
00033 #endif
00034 
00035 #ifndef _GLIBCXX_IOMANIP
00036 #include <iomanip> //for setting string stream precision.
00037 #endif
00038 
00039 UserEventHandler::UserEventHandler(osgProducer::Viewer* viewer, UserInterface* ui){
00040         _viewer = viewer;
00041         _user = ui;
00042 }
00043 
00044 bool UserEventHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us)
00045 {
00046         switch(ea.getEventType())
00047         {
00048                 case(osgGA::GUIEventAdapter::PUSH):
00049                 {
00050                         pick(ea);
00051                 }
00052                 case(osgGA::GUIEventAdapter::KEYDOWN):
00053                 {
00054                         if( ea.getKey() == 'p' )
00055                                 _user->s->pause();      
00056                 }
00057                 case(osgGA::GUIEventAdapter::FRAME):
00058                 {
00059                         _user->updateClock();
00060                         //if we want to do anything with the camera through updating the matrix, this is the place. OTOH, right now we're trying tot add the camera directly to a node through osgGA::NodeTrackerManipulator.   
00061                 }
00062                 return false;
00063                 default:
00064                 return false;
00065         }
00066 }
00067 
00068 //Alternative pick: Middle mouse button now selects.
00069 void UserEventHandler::pick(const osgGA::GUIEventAdapter& ea)
00070 {
00071   osgUtil::IntersectVisitor::HitList hlist;
00072 
00073   if (_viewer->computeIntersections(ea.getX(),ea.getY(),hlist))
00074   {
00075     for(osgUtil::IntersectVisitor::HitList::iterator hitr=hlist.begin(); hitr!=hlist.end(); ++hitr)
00076     {
00077       if (hitr->_geode.valid() && !hitr->_geode->getName().empty())
00078       {
00079         // the geodes are identified by name.
00080         unsigned int mouseButtonAction = ea.getButtonMask();
00081         if(mouseButtonAction == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)
00082         {
00083           _user->buttonAction(hitr->_geode->getParent(0)->getParent(0)->getName());
00084           if( (hitr->_geode->getParent(0)->getName() == "" ) && ( hitr->_geode->getParent(0)->getParent(0)->getName() == "" ) )
00085           {
00086              _user->buttonAction(hitr->_geode->getName());
00087           }
00088                                 }
00089                                 else if(mouseButtonAction == osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON)
00090           {
00091             osg::Group* pickedModel = dynamic_cast<osg::Group*>(hitr->_geode->getParent(0)->getParent(0));
00092             assert(pickedModel != NULL);
00093             
00094                                                 _user->selectionAction(pickedModel);
00095           }
00096       }
00097       break;  //  Only process the first hit.
00098     }
00099   }
00100 }
00101 
00102 
00103 UserInterface::UserInterface(StateControl* st){
00104         s = st;
00105         hud=NULL;
00106         hudCam = NULL;
00107         clock = NULL;
00108 }
00109 
00110 
00111 osg::Node* UserInterface::createHud(){
00112 
00113         osg::Geode* HUDGeode = new osg::Geode();
00114         hud = HUDGeode;
00115         //Set up the hud itself:
00116 
00117         HUDGeode->setName("HUD");
00118         // Set up geometry for the HUD and add it to the HUD
00119         osg::Geometry* HUDBackgroundGeometry = new osg::Geometry();
00120         osg::Vec3Array* HUDBackgroundVertices = new osg::Vec3Array;
00121         HUDBackgroundVertices->push_back( osg::Vec3( 0,    0,-1) );
00122         HUDBackgroundVertices->push_back( osg::Vec3(1280,  0,-1) );
00123         HUDBackgroundVertices->push_back( osg::Vec3(1280,200,-1) );
00124         HUDBackgroundVertices->push_back( osg::Vec3(   0,200,-1) );
00125         osg::DrawElementsUInt* HUDBackgroundIndices =
00126         new osg::DrawElementsUInt(osg::PrimitiveSet::POLYGON, 0);
00127         HUDBackgroundIndices->push_back(0);
00128         HUDBackgroundIndices->push_back(1);
00129         HUDBackgroundIndices->push_back(2);
00130         HUDBackgroundIndices->push_back(3);
00131         osg::Vec4Array* HUDcolors = new osg::Vec4Array;
00132         HUDcolors->push_back(osg::Vec4(0.8f,0.8f,0.8f,0.1f));
00133 
00134         osg::Vec2Array* texcoords = new osg::Vec2Array(4);
00135         (*texcoords)[0].set(0.0f,0.0f);
00136         (*texcoords)[1].set(1.0f,0.0f);
00137         (*texcoords)[2].set(1.0f,1.0f);
00138         (*texcoords)[3].set(0.0f,1.0f);
00139         HUDBackgroundGeometry->setTexCoordArray(0,texcoords);
00140 
00141         osg::Vec3Array* HUDnormals = new osg::Vec3Array;
00142         HUDnormals->push_back(osg::Vec3(0.0f,0.0f,1.0f));
00143         HUDBackgroundGeometry->setNormalArray(HUDnormals);
00144         HUDBackgroundGeometry->setNormalBinding(osg::Geometry::BIND_OVERALL);
00145         HUDBackgroundGeometry->addPrimitiveSet(HUDBackgroundIndices);
00146         HUDBackgroundGeometry->setVertexArray(HUDBackgroundVertices);
00147         HUDBackgroundGeometry->setColorArray(HUDcolors);
00148         HUDBackgroundGeometry->setColorBinding(osg::Geometry::BIND_OVERALL);
00149 
00150         HUDGeode->addDrawable(HUDBackgroundGeometry);
00151 
00152         osg::StateSet* HUDStateSet = new osg::StateSet();
00153         HUDGeode->setStateSet(HUDStateSet);
00154 
00155         //enable blending 
00156         HUDStateSet->setMode(GL_BLEND,osg::StateAttribute::ON);
00157 
00158         // Disable lighting.
00159         HUDStateSet->setMode(GL_LIGHTING,osg::StateAttribute::OFF);     
00160         
00161         // Disable depth testing so geometry is draw regardless of depth values
00162         // of geometry already draw.
00163         HUDStateSet->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
00164         HUDStateSet->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
00165 
00166         osg::Projection* projection = new osg::Projection;
00167         projection->setMatrix(osg::Matrix::ortho2D(0,1280,0,1024));
00168 
00169   //  Add a CameraNode to allow picking in the hud.
00170         osg::CameraNode* myview = new osg::CameraNode();
00171         hudCam = myview;
00172         myview->setProjectionMatrix(projection->getMatrix());
00173         myview->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
00174         myview->setClearMask(GL_DEPTH_BUFFER_BIT);
00175         projection->addChild(myview);
00176         
00177         osg::AutoTransform* pos = createHUDObject("Quit",true, 100, 40);
00178         myview->addChild(pos);
00179         
00180         pos = createHUDObject("Pause", true, 180, 40);
00181         myview->addChild(pos);
00182 
00183         pos = createHUDObject("-", true, 260, 40);
00184         myview->addChild(pos);
00185         
00186         pos = createHUDObject("+", true, 300, 40);
00187         myview->addChild(pos);
00188 
00189 
00190 /*TODO part of following selected objects.
00191         pos = createHUDObject("Follow", true, 380, 40);
00192         myview->addChild(pos);
00193 */
00194         //add clock:
00195         ostringstream os;
00196   os << "Time: "<< showpoint << s->getTime() << "\n Timeflow:" << s->getTimeFlow();
00197         string currentTime = os.str();  
00198         pos = createHUDObject(currentTime , false, 1000,190);
00199         myview->addChild(pos);
00200 
00201         //get a reference to the clock for updating.
00202         osg::Geode* tmpG = dynamic_cast<osg::Geode*>(pos->getChild(0));
00203         assert(tmpG != NULL);
00204 
00205         clock = dynamic_cast<osgText::Text*>(tmpG->getDrawable(0));
00206         assert(clock != NULL);
00207 
00208         return projection;
00209 }
00210 
00211 osg::AutoTransform* UserInterface::createHUDObject(string text, bool pickable, int xpos, int ypos){
00212 
00213                 osg::Geode* object = new osg::Geode();
00214                 if(pickable){
00215                         object->setName(text);
00216                 }
00217 
00218                 //label:
00219                 osgText::Text* objectText = new osgText::Text();
00220                 objectText->setCharacterSize(FONTSIZE_HUD);
00221         //      objectText->setAxisAlignment(osgText::Text::SCREEN);
00222                 objectText->setDrawMode(osgText::Text::TEXT | osgText::Text::ALIGNMENT | osgText::Text::CENTER_TOP);
00223                 objectText->setAlignment(osgText::Text::CENTER_TOP);
00224                 objectText->setText(text);
00225                 objectText->setColor(osg::Vec4d(1.0f, 0.0f, 0.0f, 1.0f) );
00226                 object->addDrawable(objectText);
00227 
00228                 osg::StateSet* s = new osg::StateSet();
00229                 // For this state set, turn blending on (so alpha texture looks right)
00230                 s->setMode(GL_BLEND,osg::StateAttribute::ON);           
00231                 // Disable lighting.
00232                 s->setMode(GL_LIGHTING,osg::StateAttribute::OFF);       
00233                 // Disable depth testing so geometry is draw regardless of depth values
00234                 // of geometry already draw.
00235                 s->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
00236                 s->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
00237                 object->setStateSet(s);                                         
00238                 
00239                 //      Add some sort of plane or shape to the Geode to allow easy picking.
00240                 osg::BoundingBox bb;
00241                 for( unsigned int i=0 ; i < object->getNumDrawables() ; ++i )
00242         {
00243             bb.expandBy( object->getDrawable(i)->getBound() );
00244         } 
00245         osg::Box *box = new osg::Box(   osg::Vec3( (bb.xMax() + bb.xMin()) / 2 , (bb.yMax() + bb.yMin()) / 2 , 0 ) , 
00246                                                                                 bb.xMax() - bb.xMin() , 
00247                                                                         bb.yMax() - bb.yMin() , 
00248                                                                         0 );
00249                 osg::ShapeDrawable *sd = new osg::ShapeDrawable( box , 0 );
00250                 sd->setColor(osg::Vec4d(1.0f, 1.0f, 1.0f, 0.0f) );
00251                 object->addDrawable( sd );
00252 
00253 
00254                 //positioning:
00255                 osg::AutoTransform* objPos = new osg::AutoTransform();
00256                 objPos->setPosition(osg::Vec3d(xpos, ypos, 0));
00257                 objPos->addChild(object);
00258 
00259                 return objPos;
00260 }
00261 
00262 void UserInterface::setHUDText(string t){
00263         hudCam->addChild( createHUDObject(t, false, 150,190) ); //Right now text is not positioned. A second text will appear on top of the 1st one.
00264 
00265 }
00266 
00267 void UserInterface::rmHUDText(string rt)
00268 {
00269         int numChildren = hudCam->getNumChildren();
00270         for(int ind = (numChildren -1); ind >= 0; ind--){
00271                 //for debugging:
00272                 osg::AutoTransform* ta = dynamic_cast<osg::AutoTransform*> (hudCam->getChild(ind));
00273                         assert(ta != NULL);
00274                 osg::Geode* tg = dynamic_cast<osg::Geode*>(ta->getChild(0));
00275                         assert(tg != NULL);
00276                 osgText::Text* td = dynamic_cast<osgText::Text*>(tg->getDrawable(0));
00277                         assert(td != NULL);
00278                 //WARNING: If the description is not uniquq, this won't work.
00279                 string hudTxt = td->getText().createUTF8EncodedString();
00280                 if(hudTxt.substr(0, hudTxt.find_first_of('\n')) == rt.substr(0,rt.find_first_of('\n'))){
00281                         hudCam->removeChild(ind);
00282                         return; //only remove the first instance that matches.
00283                 }
00284         }
00285  
00286 }
00287 
00288 
00289 bool UserInterface::buttonAction(string buttonName){
00290         if(!strcmp(buttonName.c_str(), "Quit")){
00291                 cout << "Quit button pushed, Exit." << endl;
00292                 exit(0);
00293         }
00294         if(!strcmp(buttonName.c_str(), "+")){
00295                 s->adjustTimeFlow(0.5);
00296         }else
00297         if(!strcmp(buttonName.c_str(), "-")){
00298                 s->adjustTimeFlow(-0.5);
00299         }else
00300         if(!strcmp(buttonName.c_str(), "Pause")){
00301                 s->pause();
00302         }
00303         /*TODO camera tracking of a selected object.
00304         else
00305         if(!strcmp(buttonName.c_str(), "Follow")){
00306                 s->track();
00307         }
00308         */
00309         return true;
00310 
00311 }
00312 
00313 bool UserInterface::selectionAction(osg::Node* selected){
00314         
00315         TraplasObject* tra = dynamic_cast<TraplasObject*> (selected->getUserData());
00316         if(tra == NULL){ 
00317                 cout << "Not a TraplasObject" << endl;
00318                 return false;
00319         }
00320         
00321         if(tra->isSelected()){
00322                  s->deselectObject(tra);
00323         }else{
00324                 s->clearSelection();
00325                 s->selectObject(tra);           
00326         }
00327         
00328         return true;
00329 }
00330 
00331 void UserInterface::updateClock(){
00332         ostringstream os;
00333         os << "Time: "<< showpoint << s->getTime() << "\n Timeflow:" << showpoint <<s->getTimeFlow();
00334   string currentTime = os.str();
00335         clock->setText(currentTime);
00336 }

Generated on Mon Jun 19 10:22:04 2006 for TraplasVisualisation by  doxygen 1.4.4