Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation3/src/modules/overlays/hud/HUDNavigation.cc @ 6944

Last change on this file since 6944 was 6942, checked in by scheusso, 15 years ago

merging hudelements into presentation3 and reducing (or increasing) output level of lod debug output

  • Property svn:eol-style set to native
File size: 12.5 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 *
27 */
28
29#include "HUDNavigation.h"
30
31#include <OgreCamera.h>
32#include <OgreFontManager.h>
33#include <OgreOverlayManager.h>
34#include <OgreTextAreaOverlayElement.h>
35#include <OgrePanelOverlayElement.h>
36
37#include "util/Math.h"
38#include "util/Convert.h"
39#include "core/CoreIncludes.h"
40#include "core/XMLPort.h"
41#include "CameraManager.h"
42#include "Scene.h"
43#include "Radar.h"
44#include "graphics/Camera.h"
45#include "controllers/HumanController.h"
46#include "worldentities/pawns/Pawn.h"
47#include "worldentities/WorldEntity.h"
48#include "interfaces/RadarViewable.h"
49
50namespace orxonox
51{
52    CreateFactory(HUDNavigation);
53
54    HUDNavigation::HUDNavigation(BaseObject* creator)
55        : OrxonoxOverlay(creator)
56    {
57        RegisterObject(HUDNavigation);
58
59        // Set default values
60        setFont("Monofur");
61        setTextSize(0.05f);
62        setNavMarkerSize(0.05f);
63    }
64
65    HUDNavigation::~HUDNavigation()
66    {
67        if (this->isInitialized())
68        {
69            for (ObjectMap::iterator it = activeObjectList_.begin(); it != activeObjectList_.end();)
70                removeObject((it++)->first);
71        }
72    }
73
74    void HUDNavigation::XMLPort(Element& xmlElement, XMLPort::Mode mode)
75    {
76        SUPER(HUDNavigation, XMLPort, xmlElement, mode);
77
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    }
82
83    void HUDNavigation::setFont(const std::string& font)
84    {
85        const Ogre::ResourcePtr& fontPtr = Ogre::FontManager::getSingleton().getByName(font);
86        if (fontPtr.isNull())
87        {
88            COUT(2) << "Warning: HUDNavigation: Font '" << font << "' not found" << std::endl;
89            return;
90        }
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        }
97    }
98
99    const std::string& HUDNavigation::getFont() const
100    {
101        return fontName_;
102    }
103
104    void HUDNavigation::setTextSize(float size)
105    {
106        if (size <= 0.0f)
107        {
108            COUT(2) << "Warning: HUDNavigation: Negative font size not allowed" << std::endl;
109            return;
110        }
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        }
117    }
118
119    float HUDNavigation::getTextSize() const
120    {
121        return textSize_;
122    }
123
124    void HUDNavigation::tick(float dt)
125    {
126        SUPER(HUDNavigation, tick, dt);
127
128        Camera* cam = CameraManager::getInstance().getActiveCamera();
129        if (cam == NULL)
130            return;
131        const Matrix4& camTransform = cam->getOgreCamera()->getProjectionMatrix() * cam->getOgreCamera()->getViewMatrix();
132
133        for (ObjectMap::iterator it = activeObjectList_.begin(); it != activeObjectList_.end(); ++it)
134        {
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;
139
140            // Transform to screen coordinates
141            Vector3 pos = camTransform * it->first->getRVWorldPosition();
142
143            bool outOfView = true;
144            if (pos.z > 1.0)
145            {
146                // z > 1.0 means that the object is behind the camera
147                outOfView = true;
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;
152            }
153            else
154                outOfView = pos.x < -1.0 || pos.x > 1.0 || pos.y < -1.0 || pos.y > 1.0;
155
156            if (outOfView)
157            {
158                // Object is not in view
159
160                // Change material only if outOfView changed
161                if (!it->second.wasOutOfView_)
162                {
163                    it->second.panel_->setMaterialName("Orxonox/NavArrows");
164                    it->second.wasOutOfView_ = true;
165                }
166
167                // Switch between top, bottom, left and right position of the arrow at the screen border
168                if (pos.x < pos.y)
169                {
170                    if (pos.y > -pos.x)
171                    {
172                        // Top
173                        float position = pos.x / pos.y + 1.0f;
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());
178                    }
179                    else
180                    {
181                        // Left
182                        float position = pos.y / pos.x + 1.0f;
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);
187                    }
188                }
189                else
190                {
191
192                    if (pos.y < -pos.x)
193                    {
194                        // Bottom
195                        float position = -pos.x / pos.y + 1.0f;
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());
200                    }
201                    else
202                    {
203                        // Right
204                        float position = -pos.y / pos.x + 1.0f;
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);
209                    }
210                }
211            }
212            else
213            {
214                // Object is in view
215
216                // Change material only if outOfView changed
217                if (it->second.wasOutOfView_)
218                {
219                    it->second.panel_->setMaterialName("Orxonox/NavTDC");
220                    it->second.wasOutOfView_ = false;
221                }
222
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);
227
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);
231            }
232
233            // Make sure the overlays are shown
234            it->second.panel_->show();
235            it->second.text_->show();
236        }
237    }
238
239
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;
250
251        for (ObjectMap::iterator it = activeObjectList_.begin(); it!=activeObjectList_.end(); ++it)
252        {
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);
257        }
258    }
259
260    void HUDNavigation::addObject(RadarViewable* object)
261    {
262        if (object == NULL)
263            return;
264
265        // Don't display our own ship
266        if (object == dynamic_cast<RadarViewable*>(this->getOwner()))
267            return;
268
269        // Object hasn't been added yet (we know that)
270        assert(this->activeObjectList_.find(object) == this->activeObjectList_.end());
271
272        // Scales used for dimensions and text size
273        float xScale = this->getActualSize().x;
274        float yScale = this->getActualSize().y;
275
276        // Create everything needed to display the object on the radar and add it to the map
277
278        // Create arrow/marker
279        Ogre::PanelOverlayElement* panel = static_cast<Ogre::PanelOverlayElement*>(Ogre::OverlayManager::getSingleton()
280            .createOverlayElement("Panel", "HUDNavigation_navMarker_" + getUniqueNumberString()));
281        panel->setMaterialName("Orxonox/NavTDC");
282        panel->setDimensions(navMarkerSize_ * xScale, navMarkerSize_ * yScale);
283
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);
288
289        ObjectInfo tempStruct = {panel, text, false};
290        activeObjectList_[object] = tempStruct;
291
292        this->background_->addChild(panel);
293        this->background_->addChild(text);
294    }
295
296    void HUDNavigation::removeObject(RadarViewable* viewable)
297    {
298        ObjectMap::iterator it = activeObjectList_.find(viewable);
299
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;
313    }
314
315    void HUDNavigation::changedOwner()
316    {
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        }
324    }
325}
Note: See TracBrowser for help on using the repository browser.