Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation3/src/modules/overlays/hud/HUDNavigation.cc @ 7194

Last change on this file since 7194 was 7127, checked in by rgrieder, 14 years ago

Removed excess white space at the end of lines.

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