Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation2012merge/src/modules/overlays/hud/HUDNavigation.cc @ 9279

Last change on this file since 9279 was 9279, checked in by landauf, 12 years ago

use orxonox_cast instead of dynamic_cast wherever possible

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