Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/waypoints/src/modules/overlays/hud/HUDNavigation.cc @ 9159

Last change on this file since 9159 was 9159, checked in by scmoritz, 12 years ago

3DScene added. creation of the arrow doesnt work.

  • Property svn:eol-style set to native
File size: 16.3 KB
RevLine 
[1505]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
[1454]4 *
[1505]5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
[1454]22 *   Author:
23 *      Felix Schulthess
24 *   Co-authors:
[1590]25 *      Reto Grieder
[7801]26 *      Oliver Scheuss
[9016]27 *      Matthias Spalinger
[1454]28 *
29 */
[1393]30
[1601]31#include "HUDNavigation.h"
[1410]32
[6417]33#include <OgreCamera.h>
[7163]34#include <OgreFontManager.h>
[1393]35#include <OgreOverlayManager.h>
[1614]36#include <OgreTextAreaOverlayElement.h>
37#include <OgrePanelOverlayElement.h>
[9159]38#include <OgreEntity.h>
[1410]39
[1614]40#include "util/Math.h"
[1616]41#include "util/Convert.h"
42#include "core/CoreIncludes.h"
43#include "core/XMLPort.h"
[6417]44#include "CameraManager.h"
[5929]45#include "Scene.h"
[5735]46#include "Radar.h"
[6417]47#include "graphics/Camera.h"
48#include "controllers/HumanController.h"
49#include "worldentities/pawns/Pawn.h"
[7163]50#include "worldentities/WorldEntity.h"
51#include "core/ConfigValueIncludes.h"
52#include "tools/TextureGenerator.h"
53// #include <boost/bind/bind_template.hpp>
[1393]54
[7163]55
[1393]56namespace orxonox
57{
[7163]58bool compareDistance ( std::pair<RadarViewable*, unsigned int > a, std::pair<RadarViewable*, unsigned int > b )
59{
60    return a.second<b.second;
[1590]61
[7163]62}
[2087]63
[7163]64void HUDNavigation::setConfigValues()
65{
66  SetConfigValue(markerLimit_, 3);
[9016]67  SetConfigValue(showDistance, false);
[7163]68}
[2087]69
[7163]70CreateFactory ( HUDNavigation );
[2087]71
[7163]72HUDNavigation::HUDNavigation ( BaseObject* creator )
73        : OrxonoxOverlay ( creator )
74{
75    RegisterObject ( HUDNavigation );
76    this->setConfigValues();
[2087]77
[7163]78    // Set default values
[9016]79    this->setFont ( "Monofur" );
80    this->setTextSize ( 0.05f );
81    this->setNavMarkerSize ( 0.05f );
82    this->setDetectionLimit( 10000.0f ); 
[9159]83
84    Ogre::Entity* ent = this->getScene()->getSceneManager()->createEntity("Arrow3D", "Arrow3D.mesh");
85    this->add3DMesh(ent);
86    this->overlay3d_->setPosition(0, 0, -10);
[7163]87}
[2087]88
[7163]89HUDNavigation::~HUDNavigation()
90{
91    if ( this->isInitialized() )
92    {
93        for ( ObjectMap::iterator it = activeObjectList_.begin(); it != activeObjectList_.end(); )
94            removeObject ( ( it++ )->first );
[2087]95
[1393]96    }
97
[7163]98    sortedObjectList_.clear();
99}
[1564]100
[7401]101void HUDNavigation::XMLPort ( Element& xmlelement, XMLPort::Mode mode )
[7163]102{
[7401]103    SUPER ( HUDNavigation, XMLPort, xmlelement, mode );
[1394]104
[9016]105    XMLPortParam ( HUDNavigation, "font",          setFont,          getFont,          xmlelement, mode );
106    XMLPortParam ( HUDNavigation, "textSize",      setTextSize,      getTextSize,      xmlelement, mode );
107    XMLPortParam ( HUDNavigation, "navMarkerSize", setNavMarkerSize, getNavMarkerSize, xmlelement, mode );
108    XMLPortParam ( HUDNavigation, "detectionLimit", setDetectionLimit, getDetectionLimit, xmlelement, mode ); 
[7163]109}
[1393]110
[7163]111void HUDNavigation::setFont ( const std::string& font )
112{
113    const Ogre::ResourcePtr& fontPtr = Ogre::FontManager::getSingleton().getByName ( font );
114    if ( fontPtr.isNull() )
[1590]115    {
[8858]116        orxout(internal_warning) << "HUDNavigation: Font '" << font << "' not found" << endl;
[7163]117        return;
[1590]118    }
[7163]119    fontName_ = font;
120    for ( ObjectMap::iterator it = activeObjectList_.begin(); it != activeObjectList_.end(); ++it )
[1590]121    {
[7163]122        if ( it->second.text_ != NULL )
123            it->second.text_->setFontName ( fontName_ );
[1590]124    }
[7163]125}
[1590]126
[7163]127const std::string& HUDNavigation::getFont() const
128{
129    return fontName_;
130}
131
132void HUDNavigation::setTextSize ( float size )
133{
134    if ( size <= 0.0f )
[1590]135    {
[8858]136        orxout(internal_warning) << "HUDNavigation: Negative font size not allowed" << endl;
[7163]137        return;
[1590]138    }
[7163]139    textSize_ = size;
140    for ( ObjectMap::iterator it = activeObjectList_.begin(); it!=activeObjectList_.end(); ++it )
141    {
142        if ( it->second.text_ )
143            it->second.text_->setCharHeight ( size );
144    }
145}
[1590]146
[7163]147float HUDNavigation::getTextSize() const
148{
149    return textSize_;
150}
151
[9016]152float HUDNavigation::getArrowSizeX(int dist)
153{   
154    if (dist < 600) 
155        dist = 600;
156    return this->getActualSize().x * 900 * navMarkerSize_ / dist;
157}
[7163]158
[9016]159float HUDNavigation::getArrowSizeY(int dist)
160{   
161    if (dist < 600)
162        dist = 600;   
163    return this->getActualSize().y * 900 * navMarkerSize_ / dist;
164}
[7163]165
166void HUDNavigation::tick ( float dt )
167{
168    SUPER ( HUDNavigation, tick, dt );
169
170    Camera* cam = CameraManager::getInstance().getActiveCamera();
171    if ( cam == NULL )
172        return;
173    const Matrix4& camTransform = cam->getOgreCamera()->getProjectionMatrix() * cam->getOgreCamera()->getViewMatrix();
174
175
176    for ( sortedList::iterator listIt = sortedObjectList_.begin(); listIt != sortedObjectList_.end(); ++listIt )
[1590]177    {
[7163]178        listIt->second = ( int ) ( ( listIt->first->getRVWorldPosition() - HumanController::getLocalControllerSingleton()->getControllableEntity()->getWorldPosition() ).length() + 0.5f );
[1590]179    }
180
[7163]181    sortedObjectList_.sort ( compareDistance );
182
183    unsigned int markerCount_ = 0;
[8891]184    bool closeEnough_ = false; //only display objects that are close enough to be relevant for the player
[9016]185
[7163]186//         for (ObjectMap::iterator it = activeObjectList_.begin(); it != activeObjectList_.end(); ++it)
187    for ( sortedList::iterator listIt = sortedObjectList_.begin(); listIt != sortedObjectList_.end(); ++markerCount_, ++listIt )
[1590]188    {
[7163]189        ObjectMap::iterator it = activeObjectList_.find ( listIt->first );
[8891]190        closeEnough_ = listIt->second < detectionLimit_ ;
[9016]191        // display radarviewables on HUD if the marker limit and max-distance is not exceeded
192        if ( markerCount_ < markerLimit_ && (closeEnough_ ||  detectionLimit_ < 0) ) 
[1613]193        {
[1400]194
[1399]195
[7163]196            // Get Distance to HumanController and save it in the TextAreaOverlayElement.
197            int dist = listIt->second;
[9016]198            float textLength = 0.0f;
199
200            //display distance next to cursor
201            if (showDistance){
[7163]202            it->second.text_->setCaption ( multi_cast<std::string> ( dist ) );
[9016]203            textLength = multi_cast<std::string> ( dist ).size() * it->second.text_->getCharHeight() * 0.3f;
204            }
[1564]205
[9016]206            //display name next to cursor
207            else{
208            it->second.text_->setCaption(it->first->getRVName()); 
209            textLength = it->first->getRVName().size() * it->second.text_->getCharHeight() * 0.3f;
210            }
211
[7163]212            // Transform to screen coordinates
213            Vector3 pos = camTransform * it->first->getRVWorldPosition();
[1399]214
[7163]215            bool outOfView = true;
216            if ( pos.z > 1.0 )
[1580]217            {
[7163]218                // z > 1.0 means that the object is behind the camera
219                outOfView = true;
220                // we have to switch all coordinates (if you don't know why,
221                // try linear algebra lectures, because I can't explain..)
222                pos.x = -pos.x;
223                pos.y = -pos.y;
[1411]224            }
[7163]225            else
226                outOfView = pos.x < -1.0 || pos.x > 1.0 || pos.y < -1.0 || pos.y > 1.0;
[1590]227
[7163]228            if ( outOfView )
[1580]229            {
[7163]230                // Object is not in view
231
232                // Change material only if outOfView changed
233                if ( !it->second.wasOutOfView_ )
[1580]234                {
[7368]235                    it->second.panel_->setMaterialName( TextureGenerator::getMaterialName( "arrows.png", it->first->getRadarObjectColour()) );
[7163]236                    it->second.wasOutOfView_ = true;
[1399]237                }
[7163]238
[9016]239                //float xDistScale = this->getActualSize().x * 1000.0f * navMarkerSize_ / dist;
240                //float yDistScale = this->getActualSize().y * 1000.0f * navMarkerSize_ / dist;
241
242                // Adjust Arrowsize according to distance
243                it->second.panel_->setDimensions(getArrowSizeX(dist),getArrowSizeY(dist));
244
[7163]245                // Switch between top, bottom, left and right position of the arrow at the screen border
246                if ( pos.x < pos.y )
247                {
248                    if ( pos.y > -pos.x )
249                    {
250                        // Top
251                        float position = pos.x / pos.y + 1.0f;
252                        it->second.panel_->setPosition ( ( position - it->second.panel_->getWidth() ) * 0.5f, 0.0f );
253                        it->second.panel_->setUV ( 0.5f, 0.0f, 1.0f, 0.5f );
254                        it->second.text_->setLeft ( ( position - textLength ) * 0.5f );
255                        it->second.text_->setTop ( it->second.panel_->getHeight() );
256                    }
257                    else
258                    {
259                        // Left
260                        float position = pos.y / pos.x + 1.0f;
261                        it->second.panel_->setPosition ( 0.0f, ( position - it->second.panel_->getWidth() ) * 0.5f );
262                        it->second.panel_->setUV ( 0.0f, 0.0f, 0.5f, 0.5f );
263                        it->second.text_->setLeft ( it->second.panel_->getWidth() + 0.01f );
264                        it->second.text_->setTop ( ( position - it->second.text_->getCharHeight() ) * 0.5f );
265                    }
266                }
267
[1580]268                else
269                {
[7163]270
271                    if ( pos.y < -pos.x )
272                    {
273                        // Bottom
274                        float position = -pos.x / pos.y + 1.0f;
275                        it->second.panel_->setPosition ( ( position - it->second.panel_->getWidth() ) * 0.5f, 1.0f - it->second.panel_->getHeight() );
276                        it->second.panel_->setUV ( 0.0f, 0.5f, 0.5f, 1.0f );
277                        it->second.text_->setLeft ( ( position - textLength ) * 0.5f );
278                        it->second.text_->setTop ( 1.0f - it->second.panel_->getHeight() - it->second.text_->getCharHeight() );
279                    }
280                    else
281                    {
282                        // Right
283                        float position = -pos.y / pos.x + 1.0f;
284                        it->second.panel_->setPosition ( 1.0f - it->second.panel_->getWidth(), ( position - it->second.panel_->getHeight() ) * 0.5f );
285                        it->second.panel_->setUV ( 0.5f, 0.5f, 1.0f, 1.0f );
286                        it->second.text_->setLeft ( 1.0f - it->second.panel_->getWidth() - textLength - 0.01f );
287                        it->second.text_->setTop ( ( position - it->second.text_->getCharHeight() ) * 0.5f );
288                    }
[1411]289                }
290            }
[1590]291            else
[1580]292            {
[7163]293                // Object is in view
294
295                // Change material only if outOfView changed
296                if ( it->second.wasOutOfView_ )
[1580]297                {
[7163]298                  //it->second.panel_->setMaterialName ( "Orxonox/NavTDC" );
[7368]299                    it->second.panel_->setMaterialName( TextureGenerator::getMaterialName( "tdc.png", it->first->getRadarObjectColour()) );
[9016]300                    it->second.panel_->setDimensions ( navMarkerSize_ * this->getActualSize().x, navMarkerSize_ * this->getActualSize().y );
[7163]301                    it->second.wasOutOfView_ = false;
[1399]302                }
[7163]303
304                // Position marker
305                it->second.panel_->setUV ( 0.0f, 0.0f, 1.0f, 1.0f );
306                it->second.panel_->setLeft ( ( pos.x + 1.0f - it->second.panel_->getWidth() ) * 0.5f );
307                it->second.panel_->setTop ( ( -pos.y + 1.0f - it->second.panel_->getHeight() ) * 0.5f );
308
309                // Position text
310                it->second.text_->setLeft ( ( pos.x + 1.0f + it->second.panel_->getWidth() ) * 0.5f );
311                it->second.text_->setTop ( ( -pos.y + 1.0f + it->second.panel_->getHeight() ) * 0.5f );
[1393]312            }
[7163]313
314            // Make sure the overlays are shown
315            it->second.panel_->show();
316            it->second.text_->show();
[1393]317        }
[9016]318        else // do not display on HUD
[1580]319        {
[7163]320            it->second.panel_->hide();
321            it->second.text_->hide();
322        }
[1590]323
[7163]324    }
325}
[1566]326
[7163]327
328/** Overridden method of OrxonoxOverlay.
329@details
330    Usually the entire overlay scales with scale().
331    Here we obviously have to adjust this.
[2087]332*/
[7163]333void HUDNavigation::sizeChanged()
334{
335    // Use size to compensate for aspect ratio if enabled.
336    float xScale = this->getActualSize().x;
337    float yScale = this->getActualSize().y;
338
339    for ( ObjectMap::iterator it = activeObjectList_.begin(); it!=activeObjectList_.end(); ++it )
340    {
341        if ( it->second.panel_ != NULL )
342            it->second.panel_->setDimensions ( navMarkerSize_ * xScale, navMarkerSize_ * yScale );
343        if ( it->second.text_ != NULL )
344            it->second.text_->setCharHeight ( it->second.text_->getCharHeight() * yScale );
[1410]345    }
[7163]346}
[1394]347
[7163]348void HUDNavigation::addObject ( RadarViewable* object )
349{
[9016]350    if( showObject(object)==false )
[7163]351        return;
352
353    if ( activeObjectList_.size() >= markerLimit_ )
354        if ( object == NULL )
355            return;
356
357    // Object hasn't been added yet (we know that)
358    assert ( this->activeObjectList_.find ( object ) == this->activeObjectList_.end() );
359
360    // Scales used for dimensions and text size
361    float xScale = this->getActualSize().x;
362    float yScale = this->getActualSize().y;
363
364    // Create everything needed to display the object on the radar and add it to the map
365
366    // Create arrow/marker
367    Ogre::PanelOverlayElement* panel = static_cast<Ogre::PanelOverlayElement*> ( Ogre::OverlayManager::getSingleton()
368                                       .createOverlayElement ( "Panel", "HUDNavigation_navMarker_" + getUniqueNumberString() ) );
369//     panel->setMaterialName ( "Orxonox/NavTDC" );
[7368]370    panel->setMaterialName( TextureGenerator::getMaterialName( "tdc.png", object->getRadarObjectColour()) );
[7163]371    panel->setDimensions ( navMarkerSize_ * xScale, navMarkerSize_ * yScale );
372//     panel->setColour( object->getRadarObjectColour() );
373
374    Ogre::TextAreaOverlayElement* text = static_cast<Ogre::TextAreaOverlayElement*> ( Ogre::OverlayManager::getSingleton()
375                                         .createOverlayElement ( "TextArea", "HUDNavigation_navText_" + getUniqueNumberString() ) );
376    text->setFontName ( this->fontName_ );
377    text->setCharHeight ( text->getCharHeight() * yScale );
378    text->setColour( object->getRadarObjectColour() );
379
380    panel->hide();
381    text->hide();
382
[8706]383    ObjectInfo tempStruct = {panel, text, false /*, TODO: initialize wasOutOfView_ */};
[7163]384    activeObjectList_[object] = tempStruct;
385
386    this->background_->addChild ( panel );
387    this->background_->addChild ( text );
388
389    sortedObjectList_.push_front ( std::make_pair ( object, ( unsigned int ) 0 ) );
390
391
392}
393
394void HUDNavigation::removeObject ( RadarViewable* viewable )
395{
396    ObjectMap::iterator it = activeObjectList_.find ( viewable );
397
398    if ( activeObjectList_.find ( viewable ) != activeObjectList_.end() )
[1580]399    {
[7163]400        // Detach overlays
401        this->background_->removeChild ( it->second.panel_->getName() );
402        this->background_->removeChild ( it->second.text_->getName() );
403        // Properly destroy the overlay elements (do not use delete!)
404        Ogre::OverlayManager::getSingleton().destroyOverlayElement ( it->second.panel_ );
405        Ogre::OverlayManager::getSingleton().destroyOverlayElement ( it->second.text_ );
406        // Remove from the list
407        activeObjectList_.erase ( viewable );
408
409
[1410]410    }
[1590]411
[7163]412    for ( sortedList::iterator listIt = sortedObjectList_.begin(); listIt != sortedObjectList_.end(); ++listIt )
[1590]413    {
[7163]414        if ( (listIt->first) == viewable )
415        {
416            sortedObjectList_.erase ( listIt );
417            break;
418        }
419
[1590]420    }
[7163]421
[1393]422}
[7163]423
424void HUDNavigation::objectChanged(RadarViewable* viewable)
425{
426    // TODO: niceification neccessary ;)
427    removeObject(viewable);
428    addObject(viewable);
429}
430
431
432bool HUDNavigation::showObject(RadarViewable* rv)
433{
434    if ( rv == dynamic_cast<RadarViewable*> ( this->getOwner() ) )
435        return false;
436    assert( rv->getWorldEntity() );
[9016]437    if ( rv->getWorldEntity()->isVisible()==false || rv->getRadarVisibility()==false )
[7163]438        return false;
439    return true;
440}
441
442void HUDNavigation::changedOwner()
443{
444
445    const std::set<RadarViewable*>& respawnObjects = this->getOwner()->getScene()->getRadar()->getRadarObjects();
446    for ( std::set<RadarViewable*>::const_iterator it = respawnObjects.begin(); it != respawnObjects.end(); ++it )
447    {
448        if ( ! ( *it )->isHumanShip_ )
449            this->addObject ( *it );
450    }
451}
[7801]452
[7163]453}
Note: See TracBrowser for help on using the repository browser.