Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation2012merge/src/modules/overlays/hud/HUDNavigation.cc @ 9352

Last change on this file since 9352 was 9280, checked in by landauf, 13 years ago

reformatted HUDNavigation… wtf happened here? do people know we have a style-guide?
no functional changes in code

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