Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ai2/src/modules/overlays/hud/HUDNavigation.cc @ 8781

Last change on this file since 8781 was 8706, checked in by dafrick, 13 years ago

Merging presentation branch back into trunk.
There are many new features and also a lot of other changes and bugfixes, if you want to know, digg through the svn log.
Not everything is yet working as it should, but it should be fairly stable. If you habe any bug reports, just send me an email.

  • Property svn:eol-style set to native
File size: 14.6 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 *
28 */
29
30#include "HUDNavigation.h"
31
32#include <OgreCamera.h>
33#include <OgreFontManager.h>
34#include <OgreOverlayManager.h>
35#include <OgreTextAreaOverlayElement.h>
36#include <OgrePanelOverlayElement.h>
37
38#include "util/Math.h"
39#include "util/Convert.h"
40#include "core/CoreIncludes.h"
41#include "core/XMLPort.h"
42#include "CameraManager.h"
43#include "Scene.h"
44#include "Radar.h"
45#include "graphics/Camera.h"
46#include "controllers/HumanController.h"
47#include "worldentities/pawns/Pawn.h"
48#include "worldentities/WorldEntity.h"
49#include "core/ConfigValueIncludes.h"
50#include "tools/TextureGenerator.h"
51// #include <boost/bind/bind_template.hpp>
52
53
54namespace orxonox
55{
56bool compareDistance ( std::pair<RadarViewable*, unsigned int > a, std::pair<RadarViewable*, unsigned int > b )
57{
58    return a.second<b.second;
59
60}
61
62void HUDNavigation::setConfigValues()
63{
64  SetConfigValue(markerLimit_, 3);
65}
66
67CreateFactory ( HUDNavigation );
68
69HUDNavigation::HUDNavigation ( BaseObject* creator )
70        : OrxonoxOverlay ( creator )
71{
72    RegisterObject ( HUDNavigation );
73    this->setConfigValues();
74
75    // Set default values
76    setFont ( "Monofur" );
77    setTextSize ( 0.05f );
78    setNavMarkerSize ( 0.05f );
79}
80
81HUDNavigation::~HUDNavigation()
82{
83    if ( this->isInitialized() )
84    {
85        for ( ObjectMap::iterator it = activeObjectList_.begin(); it != activeObjectList_.end(); )
86            removeObject ( ( it++ )->first );
87
88    }
89
90    sortedObjectList_.clear();
91}
92
93void HUDNavigation::XMLPort ( Element& xmlelement, XMLPort::Mode mode )
94{
95    SUPER ( HUDNavigation, XMLPort, xmlelement, mode );
96
97    XMLPortParam ( HUDNavigation, "font",          setFont,          getFont,          xmlelement, mode );
98    XMLPortParam ( HUDNavigation, "textSize",      setTextSize,      getTextSize,      xmlelement, mode );
99    XMLPortParam ( HUDNavigation, "navMarkerSize", setNavMarkerSize, getNavMarkerSize, xmlelement, mode );
100}
101
102void HUDNavigation::setFont ( const std::string& font )
103{
104    const Ogre::ResourcePtr& fontPtr = Ogre::FontManager::getSingleton().getByName ( font );
105    if ( fontPtr.isNull() )
106    {
107        COUT ( 2 ) << "Warning: HUDNavigation: Font '" << font << "' not found" << std::endl;
108        return;
109    }
110    fontName_ = font;
111    for ( ObjectMap::iterator it = activeObjectList_.begin(); it != activeObjectList_.end(); ++it )
112    {
113        if ( it->second.text_ != NULL )
114            it->second.text_->setFontName ( fontName_ );
115    }
116}
117
118const std::string& HUDNavigation::getFont() const
119{
120    return fontName_;
121}
122
123void HUDNavigation::setTextSize ( float size )
124{
125    if ( size <= 0.0f )
126    {
127        COUT ( 2 ) << "Warning: HUDNavigation: Negative font size not allowed" << std::endl;
128        return;
129    }
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}
137
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 )
156    {
157        listIt->second = ( int ) ( ( listIt->first->getRVWorldPosition() - HumanController::getLocalControllerSingleton()->getControllableEntity()->getWorldPosition() ).length() + 0.5f );
158    }
159
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 )
166    {
167        ObjectMap::iterator it = activeObjectList_.find ( listIt->first );
168
169        if ( markerCount_ < markerLimit_ )
170        {
171
172
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;
177
178            // Transform to screen coordinates
179            Vector3 pos = camTransform * it->first->getRVWorldPosition();
180
181            bool outOfView = true;
182            if ( pos.z > 1.0 )
183            {
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;
190            }
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 ) );
195
196            if ( outOfView )
197            {
198                // Object is not in view
199
200                // Change material only if outOfView changed
201                if ( !it->second.wasOutOfView_ )
202                {
203                    it->second.panel_->setMaterialName( TextureGenerator::getMaterialName( "arrows.png", it->first->getRadarObjectColour()) );
204                    it->second.wasOutOfView_ = true;
205                }
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
230                else
231                {
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                    }
251                }
252            }
253            else
254            {
255                // Object is in view
256
257                // Change material only if outOfView changed
258                if ( it->second.wasOutOfView_ )
259                {
260                  //it->second.panel_->setMaterialName ( "Orxonox/NavTDC" );
261                    it->second.panel_->setMaterialName( TextureGenerator::getMaterialName( "tdc.png", it->first->getRadarObjectColour()) );
262                    it->second.wasOutOfView_ = false;
263                }
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 );
273            }
274
275            // Make sure the overlays are shown
276            it->second.panel_->show();
277            it->second.text_->show();
278        }
279        else
280        {
281            it->second.panel_->hide();
282            it->second.text_->hide();
283        }
284
285    }
286}
287
288
289/** Overridden method of OrxonoxOverlay.
290@details
291    Usually the entire overlay scales with scale().
292    Here we obviously have to adjust this.
293*/
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 );
306    }
307}
308
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" );
331    panel->setMaterialName( TextureGenerator::getMaterialName( "tdc.png", object->getRadarObjectColour()) );
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 /*, TODO: initialize wasOutOfView_ */};
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() )
360    {
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
371    }
372
373    for ( sortedList::iterator listIt = sortedObjectList_.begin(); listIt != sortedObjectList_.end(); ++listIt )
374    {
375        if ( (listIt->first) == viewable )
376        {
377            sortedObjectList_.erase ( listIt );
378            break;
379        }
380
381    }
382
383}
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}
413
414}
Note: See TracBrowser for help on using the repository browser.