Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 8891 was 8891, checked in by jo, 13 years ago

Ai and tutorial improvements merged back to the trunk. AI features: all weapons are used, the ai-firestrength is configurable, bots are able to collect pickups . I've set the tutorial level as default level.

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