Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/hudelements/src/modules/overlays/hud/HUDNavigation.cc @ 6941

Last change on this file since 6941 was 6941, checked in by scheusso, 14 years ago

don't exactly know why, but this resolves the problem of the wrong material for arrow/marker overlay when a bot spawns inView

  • Property svn:eol-style set to native
File size: 12.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
[1454]26 *
27 */
[1393]28
[1601]29#include "HUDNavigation.h"
[1410]30
[6417]31#include <OgreCamera.h>
[6924]32#include <OgreFontManager.h>
[1393]33#include <OgreOverlayManager.h>
[1614]34#include <OgreTextAreaOverlayElement.h>
35#include <OgrePanelOverlayElement.h>
[6924]36
[1614]37#include "util/Math.h"
[1616]38#include "util/Convert.h"
39#include "core/CoreIncludes.h"
40#include "core/XMLPort.h"
[6417]41#include "CameraManager.h"
[5929]42#include "Scene.h"
[5735]43#include "Radar.h"
[6417]44#include "graphics/Camera.h"
45#include "controllers/HumanController.h"
46#include "worldentities/pawns/Pawn.h"
[6849]47#include "worldentities/WorldEntity.h"
[6897]48#include "interfaces/RadarViewable.h"
[1393]49
50namespace orxonox
51{
[6924]52    CreateFactory(HUDNavigation);
[1590]53
[6924]54    HUDNavigation::HUDNavigation(BaseObject* creator)
[2087]55        : OrxonoxOverlay(creator)
[6924]56    {
57        RegisterObject(HUDNavigation);
[6897]58
[6924]59        // Set default values
60        setFont("Monofur");
61        setTextSize(0.05f);
62        setNavMarkerSize(0.05f);
63    }
[6897]64
[6924]65    HUDNavigation::~HUDNavigation()
[1564]66    {
[6924]67        if (this->isInitialized())
68        {
69            for (ObjectMap::iterator it = activeObjectList_.begin(); it != activeObjectList_.end();)
70                removeObject((it++)->first);
71        }
[1564]72    }
73
[6924]74    void HUDNavigation::XMLPort(Element& xmlElement, XMLPort::Mode mode)
75    {
76        SUPER(HUDNavigation, XMLPort, xmlElement, mode);
[1394]77
[6924]78        XMLPortParam(HUDNavigation, "font",          setFont,          getFont,          xmlElement, mode);
79        XMLPortParam(HUDNavigation, "textSize",      setTextSize,      getTextSize,      xmlElement, mode);
80        XMLPortParam(HUDNavigation, "navMarkerSize", setNavMarkerSize, getNavMarkerSize, xmlElement, mode);
81    }
[1393]82
[6924]83    void HUDNavigation::setFont(const std::string& font)
[1590]84    {
[6924]85        const Ogre::ResourcePtr& fontPtr = Ogre::FontManager::getSingleton().getByName(font);
86        if (fontPtr.isNull())
[6874]87        {
[6924]88            COUT(2) << "Warning: HUDNavigation: Font '" << font << "' not found" << std::endl;
89            return;
[6874]90        }
[6924]91        fontName_ = font;
92        for (ObjectMap::iterator it = activeObjectList_.begin(); it != activeObjectList_.end(); ++it)
93        {
94            if (it->second.text_ != NULL)
95                it->second.text_->setFontName(fontName_);
96        }
[1590]97    }
98
[6924]99    const std::string& HUDNavigation::getFont() const
100    {
101        return fontName_;
102    }
[1590]103
[6924]104    void HUDNavigation::setTextSize(float size)
[1590]105    {
[6924]106        if (size <= 0.0f)
[6874]107        {
[6924]108            COUT(2) << "Warning: HUDNavigation: Negative font size not allowed" << std::endl;
109            return;
[6874]110        }
[6924]111        textSize_ = size;
112        for (ObjectMap::iterator it = activeObjectList_.begin(); it!=activeObjectList_.end(); ++it)
113        {
114            if (it->second.text_)
115                it->second.text_->setCharHeight(size);
116        }
[1590]117    }
118
[6924]119    float HUDNavigation::getTextSize() const
120    {
121        return textSize_;
122    }
[1590]123
[6924]124    void HUDNavigation::tick(float dt)
125    {
126        SUPER(HUDNavigation, tick, dt);
[6874]127
[6924]128        Camera* cam = CameraManager::getInstance().getActiveCamera();
129        if (cam == NULL)
130            return;
131        const Matrix4& camTransform = cam->getOgreCamera()->getProjectionMatrix() * cam->getOgreCamera()->getViewMatrix();
[2662]132
[6924]133        for (ObjectMap::iterator it = activeObjectList_.begin(); it != activeObjectList_.end(); ++it)
[1590]134        {
[6924]135            // Get Distance to HumanController and save it in the TextAreaOverlayElement.
136            int dist = (int)((it->first->getRVWorldPosition() - HumanController::getLocalControllerEntityAsPawn()->getWorldPosition()).length() + 0.5f);
137            it->second.text_->setCaption(multi_cast<std::string>(dist));
138            float textLength = multi_cast<std::string>(dist).size() * it->second.text_->getCharHeight() * 0.3f;
[1399]139
[6924]140            // Transform to screen coordinates
141            Vector3 pos = camTransform * it->first->getRVWorldPosition();
[6898]142
[6924]143            bool outOfView = true;
[6874]144            if (pos.z > 1.0)
[1580]145            {
[6874]146                // z > 1.0 means that the object is behind the camera
[6924]147                outOfView = true;
[6874]148                // we have to switch all coordinates (if you don't know why,
149                // try linear algebra lectures, because I can't explain..)
150                pos.x = -pos.x;
151                pos.y = -pos.y;
[1411]152            }
[6874]153            else
[6924]154                outOfView = pos.x < -1.0 || pos.x > 1.0 || pos.y < -1.0 || pos.y > 1.0;
[1590]155
[6924]156            if (outOfView)
[1580]157            {
[6924]158                // Object is not in view
[6874]159
[6924]160                // Change material only if outOfView changed
161                if (!it->second.wasOutOfView_)
[1580]162                {
[6924]163                    it->second.panel_->setMaterialName("Orxonox/NavArrows");
164                    it->second.wasOutOfView_ = true;
[1399]165                }
[6874]166
[6924]167                // Switch between top, bottom, left and right position of the arrow at the screen border
[6874]168                if (pos.x < pos.y)
169                {
170                    if (pos.y > -pos.x)
171                    {
[6924]172                        // Top
[6874]173                        float position = pos.x / pos.y + 1.0f;
[6924]174                        it->second.panel_->setPosition((position - it->second.panel_->getWidth()) * 0.5f, 0.0f);
175                        it->second.panel_->setUV(0.5f, 0.0f, 1.0f, 0.5f);
176                        it->second.text_->setLeft((position - textLength) * 0.5f);
177                        it->second.text_->setTop(it->second.panel_->getHeight());
[6874]178                    }
179                    else
180                    {
[6924]181                        // Left
[6874]182                        float position = pos.y / pos.x + 1.0f;
[6924]183                        it->second.panel_->setPosition(0.0f, (position - it->second.panel_->getWidth()) * 0.5f);
184                        it->second.panel_->setUV(0.0f, 0.0f, 0.5f, 0.5f);
185                        it->second.text_->setLeft(it->second.panel_->getWidth() + 0.01f);
186                        it->second.text_->setTop((position - it->second.text_->getCharHeight()) * 0.5f);
[6874]187                    }
188                }
[1580]189                else
190                {
[6875]191
[6874]192                    if (pos.y < -pos.x)
193                    {
[6924]194                        // Bottom
[6874]195                        float position = -pos.x / pos.y + 1.0f;
[6924]196                        it->second.panel_->setPosition((position - it->second.panel_->getWidth()) * 0.5f, 1.0f - it->second.panel_->getHeight());
197                        it->second.panel_->setUV(0.0f, 0.5f, 0.5f, 1.0f);
198                        it->second.text_->setLeft((position - textLength) * 0.5f);
199                        it->second.text_->setTop(1.0f - it->second.panel_->getHeight() - it->second.text_->getCharHeight());
[6874]200                    }
201                    else
202                    {
[6924]203                        // Right
[6874]204                        float position = -pos.y / pos.x + 1.0f;
[6924]205                        it->second.panel_->setPosition(1.0f - it->second.panel_->getWidth(), (position - it->second.panel_->getHeight()) * 0.5f);
206                        it->second.panel_->setUV(0.5f, 0.5f, 1.0f, 1.0f);
207                        it->second.text_->setLeft(1.0f - it->second.panel_->getWidth() - textLength - 0.01f);
208                        it->second.text_->setTop((position - it->second.text_->getCharHeight()) * 0.5f);
[6874]209                    }
[1411]210                }
211            }
[1590]212            else
[1580]213            {
[6924]214                // Object is in view
[6874]215
[6924]216                // Change material only if outOfView changed
217                if (it->second.wasOutOfView_)
[1580]218                {
[6924]219                    it->second.panel_->setMaterialName("Orxonox/NavTDC");
220                    it->second.wasOutOfView_ = false;
[1399]221                }
[1590]222
[6924]223                // Position marker
224                it->second.panel_->setUV(0.0f, 0.0f, 1.0f, 1.0f);
225                it->second.panel_->setLeft((pos.x + 1.0f - it->second.panel_->getWidth()) * 0.5f);
226                it->second.panel_->setTop((-pos.y + 1.0f - it->second.panel_->getHeight()) * 0.5f);
[1566]227
[6924]228                // Position text
229                it->second.text_->setLeft((pos.x + 1.0f + it->second.panel_->getWidth()) * 0.5f);
230                it->second.text_->setTop((-pos.y + 1.0f + it->second.panel_->getHeight()) * 0.5f);
[6874]231            }
[6875]232
[6924]233            // Make sure the overlays are shown
234            it->second.panel_->show();
235            it->second.text_->show();
[6897]236        }
[1410]237    }
[6886]238
[1590]239
[6924]240    /** Overridden method of OrxonoxOverlay.
241    @details
242        Usually the entire overlay scales with scale().
243        Here we obviously have to adjust this.
244    */
245    void HUDNavigation::sizeChanged()
246    {
247        // Use size to compensate for aspect ratio if enabled.
248        float xScale = this->getActualSize().x;
249        float yScale = this->getActualSize().y;
[6873]250
[6924]251        for (ObjectMap::iterator it = activeObjectList_.begin(); it!=activeObjectList_.end(); ++it)
[6874]252        {
[6924]253            if (it->second.panel_ != NULL)
254                it->second.panel_->setDimensions(navMarkerSize_ * xScale, navMarkerSize_ * yScale);
255            if (it->second.text_ != NULL)
256                it->second.text_->setCharHeight(it->second.text_->getCharHeight() * yScale);
[6874]257        }
[1590]258    }
[6874]259
[6924]260    void HUDNavigation::addObject(RadarViewable* object)
261    {
262        if (object == NULL)
263            return;
[6874]264
[6924]265        // Don't display our own ship
266        if (object == dynamic_cast<RadarViewable*>(this->getOwner()))
267            return;
[6874]268
[6924]269        // Object hasn't been added yet (we know that)
270        assert(this->activeObjectList_.find(object) == this->activeObjectList_.end());
[6874]271
[6924]272        // Scales used for dimensions and text size
273        float xScale = this->getActualSize().x;
274        float yScale = this->getActualSize().y;
[6874]275
[6924]276        // Create everything needed to display the object on the radar and add it to the map
[6874]277
[6924]278        // Create arrow/marker
279        Ogre::PanelOverlayElement* panel = static_cast<Ogre::PanelOverlayElement*>(Ogre::OverlayManager::getSingleton()
280            .createOverlayElement("Panel", "HUDNavigation_navMarker_" + getUniqueNumberString()));
[6941]281        panel->setMaterialName("Orxonox/NavTDC");
[6924]282        panel->setDimensions(navMarkerSize_ * xScale, navMarkerSize_ * yScale);
[6874]283
[6924]284        Ogre::TextAreaOverlayElement* text = static_cast<Ogre::TextAreaOverlayElement*>(Ogre::OverlayManager::getSingleton()
285            .createOverlayElement("TextArea", "HUDNavigation_navText_" + getUniqueNumberString()));
286        text->setFontName(this->fontName_);
287        text->setCharHeight(text->getCharHeight() * yScale);
[6874]288
[6941]289        ObjectInfo tempStruct = {panel, text, false};
[6924]290        activeObjectList_[object] = tempStruct;
[6849]291
[6924]292        this->background_->addChild(panel);
293        this->background_->addChild(text);
294    }
[6880]295
[6924]296    void HUDNavigation::removeObject(RadarViewable* viewable)
[6880]297    {
[6924]298        ObjectMap::iterator it = activeObjectList_.find(viewable);
[6880]299
[6924]300        if (activeObjectList_.find(viewable) != activeObjectList_.end())
301        {
302            // Detach overlays
303            this->background_->removeChild(it->second.panel_->getName());
304            this->background_->removeChild(it->second.text_->getName());
305            // Properly destroy the overlay elements (do not use delete!)
306            Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.panel_);
307            Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.text_);
308            // Remove from the list
309            activeObjectList_.erase(viewable);
310        }
311        else
312            COUT(2) << "Warning, HUDNavigation: Attempting to remove non-existent object" << std::endl;
[6880]313    }
[6874]314
[6924]315    void HUDNavigation::changedOwner()
[6898]316    {
[6924]317        // TODO: Delete old objects?
318        const std::set<RadarViewable*>& respawnObjects = this->getOwner()->getScene()->getRadar()->getRadarObjects();
319        for (std::set<RadarViewable*>::const_iterator it = respawnObjects.begin(); it != respawnObjects.end(); ++it)
320        {
321            if (!(*it)->isHumanShip_)
322                this->addObject(*it);
323        }
[6898]324    }
325}
Note: See TracBrowser for help on using the repository browser.