Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

renamed RVName to radarname
cast to RadarViewable instead of SpaceShip to set the name (in PlayerInfo)

  • Property svn:eol-style set to native
File size: 16.1 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
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 *
22 *   Author:
23 *      Felix Schulthess
24 *   Co-authors:
25 *      Reto Grieder
26 *      Oliver Scheuss
27 *      Matthias Spalinger
28 *
29 */
30
31#include "HUDNavigation.h"
32
33#include <OgreCamera.h>
34#include <OgreFontManager.h>
35#include <OgreOverlayManager.h>
36#include <OgreTextAreaOverlayElement.h>
37#include <OgrePanelOverlayElement.h>
38
39#include "util/Math.h"
40#include "util/Convert.h"
41#include "core/CoreIncludes.h"
42#include "core/XMLPort.h"
43#include "CameraManager.h"
44#include "Scene.h"
45#include "Radar.h"
46#include "graphics/Camera.h"
47#include "controllers/HumanController.h"
48#include "worldentities/pawns/Pawn.h"
49#include "worldentities/WorldEntity.h"
50#include "core/ConfigValueIncludes.h"
51#include "tools/TextureGenerator.h"
52// #include <boost/bind/bind_template.hpp>
53
54
55namespace orxonox
56{
57bool compareDistance ( std::pair<RadarViewable*, unsigned int > a, std::pair<RadarViewable*, unsigned int > b )
58{
59    return a.second<b.second;
60
61}
62
63void HUDNavigation::setConfigValues()
64{
65  SetConfigValue(markerLimit_, 3);
66  SetConfigValue(showDistance, false);
67}
68
69CreateFactory ( HUDNavigation );
70
71HUDNavigation::HUDNavigation ( BaseObject* creator )
72        : OrxonoxOverlay ( creator )
73{
74    RegisterObject ( HUDNavigation );
75    this->setConfigValues();
76
77    // Set default values
78    this->setFont ( "Monofur" );
79    this->setTextSize ( 0.05f );
80    this->setNavMarkerSize ( 0.05f );
81    this->setDetectionLimit( 10000.0f );
82}
83
84HUDNavigation::~HUDNavigation()
85{
86    if ( this->isInitialized() )
87    {
88        for ( ObjectMap::iterator it = activeObjectList_.begin(); it != activeObjectList_.end(); )
89            removeObject ( ( it++ )->first );
90
91    }
92
93    sortedObjectList_.clear();
94}
95
96void HUDNavigation::XMLPort ( Element& xmlelement, XMLPort::Mode mode )
97{
98    SUPER ( HUDNavigation, XMLPort, xmlelement, mode );
99
100    XMLPortParam ( HUDNavigation, "font",          setFont,          getFont,          xmlelement, mode );
101    XMLPortParam ( HUDNavigation, "textSize",      setTextSize,      getTextSize,      xmlelement, mode );
102    XMLPortParam ( HUDNavigation, "navMarkerSize", setNavMarkerSize, getNavMarkerSize, xmlelement, mode );
103    XMLPortParam ( HUDNavigation, "detectionLimit", setDetectionLimit, getDetectionLimit, xmlelement, mode );
104}
105
106void HUDNavigation::setFont ( const std::string& font )
107{
108    const Ogre::ResourcePtr& fontPtr = Ogre::FontManager::getSingleton().getByName ( font );
109    if ( fontPtr.isNull() )
110    {
111        orxout(internal_warning) << "HUDNavigation: Font '" << font << "' not found" << endl;
112        return;
113    }
114    fontName_ = font;
115    for ( ObjectMap::iterator it = activeObjectList_.begin(); it != activeObjectList_.end(); ++it )
116    {
117        if ( it->second.text_ != NULL )
118            it->second.text_->setFontName ( fontName_ );
119    }
120}
121
122const std::string& HUDNavigation::getFont() const
123{
124    return fontName_;
125}
126
127void HUDNavigation::setTextSize ( float size )
128{
129    if ( size <= 0.0f )
130    {
131        orxout(internal_warning) << "HUDNavigation: Negative font size not allowed" << endl;
132        return;
133    }
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}
141
142float HUDNavigation::getTextSize() const
143{
144    return textSize_;
145}
146
147float HUDNavigation::getArrowSizeX(int dist)
148{
149    if (dist < 600)
150        dist = 600;
151    return this->getActualSize().x * 900 * navMarkerSize_ / dist;
152}
153
154float HUDNavigation::getArrowSizeY(int dist)
155{
156    if (dist < 600)
157        dist = 600;
158    return this->getActualSize().y * 900 * navMarkerSize_ / dist;
159}
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 )
172    {
173        listIt->second = ( int ) ( ( listIt->first->getRVWorldPosition() - HumanController::getLocalControllerSingleton()->getControllableEntity()->getWorldPosition() ).length() + 0.5f );
174    }
175
176    sortedObjectList_.sort ( compareDistance );
177
178    unsigned int markerCount_ = 0;
179    bool closeEnough_ = false; //only display objects that are close enough to be relevant for the player
180
181//         for (ObjectMap::iterator it = activeObjectList_.begin(); it != activeObjectList_.end(); ++it)
182    for ( sortedList::iterator listIt = sortedObjectList_.begin(); listIt != sortedObjectList_.end(); ++markerCount_, ++listIt )
183    {
184        ObjectMap::iterator it = activeObjectList_.find ( listIt->first );
185        closeEnough_ = listIt->second < detectionLimit_ ;
186        // display radarviewables on HUD if the marker limit and max-distance is not exceeded
187        if ( markerCount_ < markerLimit_ && (closeEnough_ ||  detectionLimit_ < 0) )
188        {
189
190
191            // Get Distance to HumanController and save it in the TextAreaOverlayElement.
192            int dist = listIt->second;
193            float textLength = 0.0f;
194
195            //display distance next to cursor
196            if (showDistance){
197            it->second.text_->setCaption ( multi_cast<std::string> ( dist ) );
198            textLength = multi_cast<std::string> ( dist ).size() * it->second.text_->getCharHeight() * 0.3f;
199            }
200
201            //display name next to cursor
202            else{
203            it->second.text_->setCaption(it->first->getRadarName());
204            textLength = it->first->getRadarName().size() * it->second.text_->getCharHeight() * 0.3f;
205            }
206
207            // Transform to screen coordinates
208            Vector3 pos = camTransform * it->first->getRVWorldPosition();
209
210            bool outOfView = true;
211            if ( pos.z > 1.0 )
212            {
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;
219            }
220            else
221                outOfView = pos.x < -1.0 || pos.x > 1.0 || pos.y < -1.0 || pos.y > 1.0;
222
223            if ( outOfView )
224            {
225                // Object is not in view
226
227                // Change material only if outOfView changed
228                if ( !it->second.wasOutOfView_ )
229                {
230                    it->second.panel_->setMaterialName( TextureGenerator::getMaterialName( "arrows.png", it->first->getRadarObjectColour()) );
231                    it->second.wasOutOfView_ = true;
232                }
233
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
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
263                else
264                {
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                    }
284                }
285            }
286            else
287            {
288                // Object is in view
289
290                // Change material only if outOfView changed
291                if ( it->second.wasOutOfView_ )
292                {
293                  //it->second.panel_->setMaterialName ( "Orxonox/NavTDC" );
294                    it->second.panel_->setMaterialName( TextureGenerator::getMaterialName( "tdc.png", it->first->getRadarObjectColour()) );
295                    it->second.panel_->setDimensions ( navMarkerSize_ * this->getActualSize().x, navMarkerSize_ * this->getActualSize().y );
296                    it->second.wasOutOfView_ = false;
297                }
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 );
307            }
308
309            // Make sure the overlays are shown
310            it->second.panel_->show();
311            it->second.text_->show();
312        }
313        else // do not display on HUD
314        {
315            it->second.panel_->hide();
316            it->second.text_->hide();
317        }
318
319    }
320}
321
322
323/** Overridden method of OrxonoxOverlay.
324@details
325    Usually the entire overlay scales with scale().
326    Here we obviously have to adjust this.
327*/
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 );
340    }
341}
342
343void HUDNavigation::addObject ( RadarViewable* object )
344{
345    if( showObject(object)==false )
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" );
365    panel->setMaterialName( TextureGenerator::getMaterialName( "tdc.png", object->getRadarObjectColour()) );
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
378    ObjectInfo tempStruct = {panel, text, false /*, TODO: initialize wasOutOfView_ */};
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() )
394    {
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
405    }
406
407    for ( sortedList::iterator listIt = sortedObjectList_.begin(); listIt != sortedObjectList_.end(); ++listIt )
408    {
409        if ( (listIt->first) == viewable )
410        {
411            sortedObjectList_.erase ( listIt );
412            break;
413        }
414
415    }
416
417}
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{
429    if ( rv == dynamic_cast<RadarViewable*> ( this->getOwner() ) )
430        return false;
431    assert( rv->getWorldEntity() );
432    if ( rv->getWorldEntity()->isVisible()==false || rv->getRadarVisibility()==false )
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}
447
448}
Note: See TracBrowser for help on using the repository browser.