Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/modules/overlays/hud/HUDNavigation.cc @ 8340

Last change on this file since 8340 was 7801, checked in by dafrick, 14 years ago

Merging presentation2 branch back to trunk.

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