Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 6922 was 6922, checked in by rgrieder, 14 years ago

Fixed bug in HUDNavigation destructor again.

  • Property svn:eol-style set to native
File size: 15.8 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#include <utility>
31
32#include <string>
33#include <OgreCamera.h>
34#include <OgreOverlayManager.h>
35#include <OgreTextAreaOverlayElement.h>
36#include <OgrePanelOverlayElement.h>
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{
52CreateFactory(HUDNavigation);
53
54HUDNavigation::HUDNavigation(BaseObject* creator)
55        : OrxonoxOverlay(creator)
56{
57    RegisterObject(HUDNavigation);
58
59    setFont("Monofur");
60    setTextSize(0.05f);
61    setNavMarkerSize(0.05f);
62
63
64   
65//         // create nav text
66//         navText_ = static_cast<Ogre::TextAreaOverlayElement*>(Ogre::OverlayManager::getSingleton()
67//             .createOverlayElement("TextArea", "HUDNavigation_navText_" + getUniqueNumberString()));
68//
69//         // create nav marker
70//         navMarker_ = static_cast<Ogre::PanelOverlayElement*>(Ogre::OverlayManager::getSingleton()
71//             .createOverlayElement("Panel", "HUDNavigation_navMarker_" + getUniqueNumberString()));
72//         navMarker_->setMaterialName("Orxonox/NavArrows");
73
74        /*
75                // create aim marker
76                aimMarker_ = static_cast<Ogre::PanelOverlayElement*>(Ogre::OverlayManager::getSingleton()
77                    .createOverlayElement("Panel", "HUDNavigation_aimMarker_" + getUniqueNumberString()));
78                aimMarker_->setMaterialName("Orxonox/NavCrosshair");
79                this->wasOutOfView_ = true; // Ensure the material is changed right the first time..
80
81
82        */
83        /*
84                background_->addChild(navMarker_);*/
85//        background_->addChild(aimMarker_);
86//         background_->addChild(navText_);
87
88        // hide at first
89//         this->setVisible(false);
90
91
92
93//         setAimMarkerSize(0.04f);
94   
95}
96
97HUDNavigation::~HUDNavigation()
98{
99    if (this->isInitialized())
100    {
101        for (activeObjectListType::iterator it = activeObjectList_.begin(); it != activeObjectList_.end();)
102            removeObject((it++)->first);
103    }
104}
105
106void HUDNavigation::XMLPort(Element& xmlElement, XMLPort::Mode mode)
107{
108    SUPER(HUDNavigation, XMLPort, xmlElement, mode);
109
110    XMLPortParam(HUDNavigation, "font",     setFont,     getFont,     xmlElement, mode);
111    XMLPortParam(HUDNavigation, "textSize", setTextSize, getTextSize, xmlElement, mode);
112    XMLPortParam(HUDNavigation, "navMarkerSize", setNavMarkerSize, getNavMarkerSize, xmlElement, mode);
113//        XMLPortParam(HUDNavigation, "aimMarkerSize", setAimMarkerSize, getAimMarkerSize, xmlElement, mode);
114}
115
116void HUDNavigation::setFont(const std::string& font)
117{
118    fontName_ = font;
119    if (!activeObjectList_.empty())
120    {
121        for (tempRadarViewable = activeObjectList_.begin(); tempRadarViewable!=activeObjectList_.end(); ++tempRadarViewable)
122        {
123            if (tempRadarViewable->second.text_ && !fontName_.empty())
124                tempRadarViewable->second.text_->setFontName(fontName_);
125        }
126    }
127}
128
129const std::string& HUDNavigation::getFont() const
130{
131    return fontName_;
132}
133
134void HUDNavigation::setTextSize(float size)
135{
136    textSize_ = size;
137    if (!activeObjectList_.empty())
138    {
139        for (tempRadarViewable = activeObjectList_.begin(); tempRadarViewable!=activeObjectList_.end(); ++tempRadarViewable)
140        {
141            if (tempRadarViewable->second.text_ && size >= 0.0f)
142                tempRadarViewable->second.text_->setCharHeight(size);
143        }
144    }
145}
146
147float HUDNavigation::getTextSize() const
148{
149    return textSize_;
150}
151
152void HUDNavigation::tick(float dt)
153{
154    SUPER(HUDNavigation, tick, dt);
155
156//      updateActiveObjectList(activeObjectList_);
157
158    // Get radar
159//         Radar* radar = this->getOwner()->getScene()->getRadar();
160//
161//         if (!radar->getFocus())
162//         {
163//             this->overlay_->hide();
164//             return;
165//         }
166//         else
167//         {
168//             this->overlay_->show();
169//         }
170
171    // set text
172//         int dist = static_cast<int>(getDist2Focus());
173//         navText_->setCaption(multi_cast<std::string>(dist));
174//         float textLength = multi_cast<std::string>(dist).size() * navText_->getCharHeight() * 0.3f;
175
176    if (!activeObjectList_.empty())
177    {
178        for (tempRadarViewable = activeObjectList_.begin(); tempRadarViewable!=activeObjectList_.end(); ++tempRadarViewable)
179        {
180
181
182            //get Distance to HumanController and save it in the TextAreaOverlayElement.
183            int dist = (int)(tempRadarViewable->first->getRVWorldPosition() - HumanController::getLocalControllerEntityAsPawn()->getWorldPosition()).length();
184            tempRadarViewable->second.text_->setCaption(multi_cast<std::string>(dist));
185            float textLength = multi_cast<std::string>(dist).size() * tempRadarViewable->second.text_->getCharHeight() * 0.3f;
186
187
188
189            orxonox::Camera* cam = CameraManager::getInstance().getActiveCamera();
190            if (!cam)
191                return;
192            const Matrix4& transform = cam->getOgreCamera()->getProjectionMatrix() * cam->getOgreCamera()->getViewMatrix();
193            // transform to screen coordinates
194            Vector3 pos = transform * tempRadarViewable->first->getRVWorldPosition();
195
196
197
198
199            if (pos.z > 1.0)
200            {
201                // z > 1.0 means that the object is behind the camera
202                tempRadarViewable->second.outOfView_ = true;
203                // we have to switch all coordinates (if you don't know why,
204                // try linear algebra lectures, because I can't explain..)
205                pos.x = -pos.x;
206                pos.y = -pos.y;
207            }
208            else
209                tempRadarViewable->second.outOfView_ = pos.x < -1.0 || pos.x > 1.0 || pos.y < -1.0 || pos.y > 1.0;
210
211            if (tempRadarViewable->second.outOfView_)
212            {
213                // object is not in view
214//            aimMarker_->hide();
215
216                if (!tempRadarViewable->second.wasOutOfView_)
217                {
218                    tempRadarViewable->second.panel_->setMaterialName("Orxonox/NavArrows");
219                    tempRadarViewable->second.wasOutOfView_ = true;
220                }
221
222
223
224                if (pos.x < pos.y)
225                {
226                    if (pos.y > -pos.x)
227                    {
228                        // up
229                        float position = pos.x / pos.y + 1.0f;
230                        tempRadarViewable->second.panel_->setPosition((position - tempRadarViewable->second.panel_->getWidth()) * 0.5f, 0.0f);
231                        tempRadarViewable->second.panel_->setUV(0.5f, 0.0f, 1.0f, 0.5f);
232                        tempRadarViewable->second.text_->setLeft((position - textLength) * 0.5f);
233                        tempRadarViewable->second.text_->setTop(tempRadarViewable->second.panel_->getHeight());
234                    }
235                    else
236                    {
237                        // left
238                        float position = pos.y / pos.x + 1.0f;
239                        tempRadarViewable->second.panel_->setPosition(0.0f, (position - tempRadarViewable->second.panel_->getWidth()) * 0.5f);
240                        tempRadarViewable->second.panel_->setUV(0.0f, 0.0f, 0.5f, 0.5f);
241                        tempRadarViewable->second.text_->setLeft(tempRadarViewable->second.panel_->getWidth() + 0.01f);
242                        tempRadarViewable->second.text_->setTop((position - tempRadarViewable->second.text_->getCharHeight()) * 0.5f);
243                    }
244                }
245                else
246                {
247
248                    if (pos.y < -pos.x)
249                    {
250                        // down
251                        float position = -pos.x / pos.y + 1.0f;
252                        tempRadarViewable->second.panel_->setPosition((position - tempRadarViewable->second.panel_->getWidth()) * 0.5f, 1.0f - tempRadarViewable->second.panel_->getHeight());
253                        tempRadarViewable->second.panel_->setUV(0.0f, 0.5f, 0.5f, 1.0f);
254                        tempRadarViewable->second.text_->setLeft((position - textLength) * 0.5f);
255                        tempRadarViewable->second.text_->setTop(1.0f - tempRadarViewable->second.panel_->getHeight() - tempRadarViewable->second.text_->getCharHeight());
256                    }
257                    else
258                    {
259                        // right
260                        float position = -pos.y / pos.x + 1.0f;
261                        tempRadarViewable->second.panel_->setPosition(1.0f - tempRadarViewable->second.panel_->getWidth(), (position - tempRadarViewable->second.panel_->getHeight()) * 0.5f);
262                        tempRadarViewable->second.panel_->setUV(0.5f, 0.5f, 1.0f, 1.0f);
263                        tempRadarViewable->second.text_->setLeft(1.0f - tempRadarViewable->second.panel_->getWidth() - textLength - 0.01f);
264                        tempRadarViewable->second.text_->setTop((position - tempRadarViewable->second.text_->getCharHeight()) * 0.5f);
265                    }
266                }
267            }
268            else
269            {
270
271
272                // object is in view
273                /*
274                            Vector3 aimpos = transform * getPredictedPosition(SpaceShip::getLocalShip()->getPosition(),
275                                    Projectile::getSpeed(), Radar::getInstance().getFocus()->getRVWorldPosition(), Radar::getInstance().getFocus()->getRVOrientedVelocity());
276                */
277                if (tempRadarViewable->second.wasOutOfView_)
278                {
279                    tempRadarViewable->second.panel_->setMaterialName("Orxonox/NavTDC");
280                    tempRadarViewable->second.wasOutOfView_ = false;
281                }
282
283                // object is in view
284                tempRadarViewable->second.panel_->setUV(0.0f, 0.0f, 1.0f, 1.0f);
285                tempRadarViewable->second.panel_->setLeft((pos.x + 1.0f - tempRadarViewable->second.panel_->getWidth()) * 0.5f);
286                tempRadarViewable->second.panel_->setTop((-pos.y + 1.0f - tempRadarViewable->second.panel_->getHeight()) * 0.5f);
287
288
289//                 aimMarker_->show();
290//                 aimMarker_->setLeft((aimpos.x + 1.0f - aimMarker_->getWidth()) * 0.5f);
291//                 aimMarker_->setTop((-aimpos.y + 1.0f - aimMarker_->getHeight()) * 0.5f);
292//
293                tempRadarViewable->second.text_->setLeft((pos.x + 1.0f + tempRadarViewable->second.panel_->getWidth()) * 0.5f);
294                tempRadarViewable->second.text_->setTop((-pos.y + 1.0f + tempRadarViewable->second.panel_->getHeight()) * 0.5f);
295            }
296
297            tempRadarViewable->second.panel_->show();
298            tempRadarViewable->second.text_->show();
299//             tempRadarViewable->second.text_->hide();
300        }
301
302    }
303
304}
305
306
307// float HUDNavigation::getDist2Focus() const {
308//
309//     Radar* radar = this->getOwner()->getScene()->getRadar();
310//     if (radar->getFocus() && HumanController::getLocalControllerEntityAsPawn())
311//         return (radar->getFocus()->getRVWorldPosition() - HumanController::getLocalControllerEntityAsPawn()->getWorldPosition()).length();
312//     else
313//         return 0;
314// }
315
316/**
317@brief Overridden method of OrxonoxOverlay. Usually the entire overlay
318       scales with scale(). Here we obviously have to adjust this.
319*/
320void HUDNavigation::sizeChanged()
321{
322    // use size to compensate for aspect ratio if enabled.
323    float xScale = this->getActualSize().x;
324    float yScale = this->getActualSize().y;
325
326    if (!activeObjectList_.empty())
327    {
328        for (tempRadarViewable = activeObjectList_.begin(); tempRadarViewable!=activeObjectList_.end(); ++tempRadarViewable)
329        {
330
331            if (tempRadarViewable->second.panel_)
332                tempRadarViewable->second.panel_->setDimensions(navMarkerSize_ * xScale, navMarkerSize_ * yScale);
333//            if (this->aimMarker_)
334//            aimMarker_->setDimensions(aimMarkerSize_ * xScale, aimMarkerSize_ * yScale);
335            if (tempRadarViewable->second.text_)
336                tempRadarViewable->second.text_->setCharHeight(tempRadarViewable->second.text_->getCharHeight() * yScale);
337        }
338    }
339}
340
341
342void HUDNavigation::addObject(RadarViewable* object)
343{
344    if (object == dynamic_cast<RadarViewable*>(this->getOwner()))
345        return;
346
347    assert(object);
348
349    // Make sure the object hasn't been added yet
350    assert( this->activeObjectList_.find(object) == this->activeObjectList_.end() );
351
352    // Create everything needed to display the object on the radar and add it to the map
353
354    // create nav marker
355    Ogre::PanelOverlayElement* panel = static_cast<Ogre::PanelOverlayElement*>(Ogre::OverlayManager::getSingleton()
356                                       .createOverlayElement("Panel", "HUDNavigation_navMarker_" + getUniqueNumberString()));
357
358    panel->setMaterialName("Orxonox/NavArrows");
359
360    Ogre::TextAreaOverlayElement* text = static_cast<Ogre::TextAreaOverlayElement*>(Ogre::OverlayManager::getSingleton()
361                                         .createOverlayElement("TextArea", "HUDNavigation_navText_" + getUniqueNumberString()));
362               
363   
364    float xScale = this->getActualSize().x;
365    float yScale = this->getActualSize().y;
366
367    panel->setDimensions(navMarkerSize_ * xScale, navMarkerSize_ * yScale);
368    text->setCharHeight(text->getCharHeight() * yScale);
369
370    objectStruct tempStruct = {panel, text, true};
371    activeObjectList_[object] = tempStruct;
372
373    this->background_->addChild(panel);
374    this->background_->addChild(text);
375
376//      background_->addChild(activeObjectList_[object].first);
377//      background_->addChild(activeObjectList_[object].second);
378
379}
380
381void HUDNavigation::removeObject(RadarViewable* viewable)
382{
383    activeObjectListType::iterator it = activeObjectList_.find(viewable);
384
385    if (activeObjectList_.find(viewable) != activeObjectList_.end())
386    {
387        // Remove overlays from Ogre
388        this->background_->removeChild(it->second.panel_->getName());
389        this->background_->removeChild(it->second.text_->getName());
390        // correctly destroy the overlay elements
391        Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.panel_);
392        Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.text_);
393
394        activeObjectList_.erase(viewable);
395    }
396   
397}
398
399void HUDNavigation::changedOwner()
400{
401    respawnObjectSetType respawnObjectSet = this->getOwner()->getScene()->getRadar()->getRadarObjects();
402    respawnObjectSetType::iterator respawnObjectSetIt_;
403    for (respawnObjectSetIt_ = respawnObjectSet.begin(); respawnObjectSetIt_ != respawnObjectSet.end(); ++respawnObjectSetIt_)
404    {
405        if (!(*respawnObjectSetIt_)->isHumanShip_)
406            this->addObject(*respawnObjectSetIt_);
407    }
408
409}
410
411
412
413//      void updateActiveObjectList(map activeObjectList_){}
414//
415//      void HUDNavigation::objectChanged(RadarViewable* viewable){}
416//
417//
418//         float HUDNavigation::getRadarSensitivity(){}
419//         void HUDNavigation::radarTick(float dt){}
420
421
422}
423
424
Note: See TracBrowser for help on using the repository browser.