Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/hud/src/orxonox/overlays/hud/HUDNavigation.cc @ 1604

Last change on this file since 1604 was 1604, checked in by rgrieder, 16 years ago
  • adjusted Radar to fit in XML loading scheme
  • OverlayGroup should be more or less what I imagine for now (only supports scale method to scale the entire HUD)
  • singletonized HUDNavigation (and HUDRadar of course): These are temporary hacks!
  • Property svn:eol-style set to native
File size: 13.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 "OrxonoxStableHeaders.h"
30#include "HUDNavigation.h"
31
32#include <OgreOverlayManager.h>
33#include <OgreStringConverter.h>
34
35//#include "GraphicsEngine.h"
36// TODO: remove the SpaceShip and CameraHandler dependencies
37#include "core/Debug.h"
38#include "core/CoreIncludes.h"
39#include "core/ConsoleCommand.h"
40#include "objects/SpaceShip.h"
41#include "objects/Projectile.h"
42#include "objects/CameraHandler.h"
43#include "overlays/OverlayGroup.h"
44#include "RadarObject.h"
45#include "HUDRadar.h"
46
47namespace orxonox
48{
49    CreateFactory(HUDNavigation);
50
51    SetConsoleCommand(HUDNavigation, cycleNavigationFocus, true).setAccessLevel(AccessLevel::User);
52    SetConsoleCommand(HUDNavigation, releaseNavigationFocus, true).setAccessLevel(AccessLevel::User);
53
54    HUDNavigation* HUDNavigation::instance_s = 0;
55
56    using namespace Ogre;
57
58    HUDNavigation::HUDNavigation()
59      : container_(0)
60      , navMarker_(0)
61      , aimMarker_(0)
62      , navText_(0)
63      , focus_(0)
64    {
65        RegisterObject(HUDNavigation);
66       
67        assert(instance_s == 0); // singleton class
68        HUDNavigation::instance_s = this;
69    }
70
71    HUDNavigation::~HUDNavigation()
72    {
73        if (this->isInitialized())
74        {
75            if (this->container_)
76                OverlayManager::getSingleton().destroyOverlayElement(this->container_);
77            if (this->navMarker_)
78                OverlayManager::getSingleton().destroyOverlayElement(this->navMarker_);
79            if (this->navText_)
80                OverlayManager::getSingleton().destroyOverlayElement(this->navText_);
81            if (this->aimMarker_)
82                OverlayManager::getSingleton().destroyOverlayElement(this->aimMarker_);
83        }
84
85        HUDNavigation::instance_s = 0;
86    }
87
88    void HUDNavigation::XMLPort(Element& xmlElement, XMLPort::Mode mode)
89    {
90        OrxonoxOverlay::XMLPort(xmlElement, mode);
91
92        if (mode == XMLPort::LoadObject)
93        {
94            // create container
95            container_ = static_cast<OverlayContainer*>(Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", getName() + "_navContainer"));
96
97            // create nav text
98            navText_ = static_cast<TextAreaOverlayElement*>(Ogre::OverlayManager::getSingleton().createOverlayElement("TextArea", getName() + "_navText"));
99            navText_->setCharHeight(0.05f);
100            navText_->setFontName("Monofur");
101
102            // create nav marker
103            navMarker_ = static_cast<PanelOverlayElement*>(OverlayManager::getSingleton().createOverlayElement("Panel", getName() + "_navMarker"));
104            navMarker_->setMaterialName("Orxonox/NavArrows");
105            navMarkerSize_ = 0.05; //default
106            wasOutOfView_ = true; // just to ensure the material is changed right the first time..
107
108            // create aim marker
109            aimMarker_ = static_cast<PanelOverlayElement*>(OverlayManager::getSingleton().createOverlayElement("Panel", getName() + "_aimMarker"));
110            aimMarker_->setMaterialName("Orxonox/NavCrosshair");
111            aimMarkerSize_ = 0.04; // default
112           
113            container_->addChild(navMarker_);
114            container_->addChild(aimMarker_);
115            container_->addChild(navText_);
116            container_->show();
117
118            overlay_->add2D(container_);
119            overlay_->hide();
120        }
121
122        XMLPortParam(HUDNavigation, "font", setFont, getFont, xmlElement, mode);
123        XMLPortParam(HUDNavigation, "textsize", setTextSize, getTextSize, xmlElement, mode);
124        XMLPortParam(HUDNavigation, "navmarkersize", setNavMarkerSize, getNavMarkerSize, xmlElement, mode);
125        XMLPortParam(HUDNavigation, "aimmarkersize", setAimMarkerSize, getAimMarkerSize, xmlElement, mode);
126
127        if (mode == XMLPort::LoadObject)
128        {
129            this->sizeChanged();
130        }
131    }
132
133    void HUDNavigation::setNavMarkerSize(float size)
134    {
135        this->navMarkerSize_ = size;
136    }
137
138    float HUDNavigation::getNavMarkerSize() const
139    {
140        return this->navMarkerSize_;
141    }
142
143    void HUDNavigation::setAimMarkerSize(float size)
144    {
145        this->aimMarkerSize_ = size;
146    }
147
148    float HUDNavigation::getAimMarkerSize() const
149    {
150        return this->aimMarkerSize_;
151    }
152
153    void HUDNavigation::setFont(const std::string& font)
154    {
155        if (this->navText_ && font != "")
156            this->navText_->setFontName(font);
157    }
158
159    std::string HUDNavigation::getFont() const
160    {
161        if (this->navText_)
162            return this->navText_->getFontName();
163        else
164            return "";
165    }
166
167    void HUDNavigation::setTextSize(float size)
168    {
169        if (this->navText_ && size >= 0.0f)
170            this->navText_->setCharHeight(size);
171    }
172
173    float HUDNavigation::getTextSize() const
174    {
175        if (this->navText_)
176            return this->navText_->getCharHeight();
177        else
178            return 0.0f;
179    }
180
181    void HUDNavigation::tick(float dt)
182    {
183        if (!focus_)
184            return;
185
186        // set text
187        int dist = (int) getDist2Focus()/100.0f;
188        navText_->setCaption(convertToString(dist));
189        float textLength = convertToString(dist).size() * navText_->getCharHeight() * 0.3;
190
191        Ogre::Camera* navCam = SpaceShip::getLocalShip()->getCamera()->cam_;
192        Matrix4 transformationMatrix = navCam->getProjectionMatrix() * navCam->getViewMatrix();
193        // transform to screen coordinates
194        Vector3 pos = transformationMatrix * focus_->getPosition();
195
196        bool outOfView;
197        if (pos.z > 1.0)
198        {
199            // z > 1.0 means that the object is behind the camera
200            outOfView = true;
201            // we have to switch all coordinates (if you don't know why,
202            // try linear algebra lectures, because I can't explain..)
203            pos.x = -pos.x;
204            pos.y = -pos.y;
205        }
206        else
207            outOfView = pos.x < -1.0 || pos.x > 1.0 || pos.y < -1.0 || pos.y > 1.0;
208
209        if (outOfView)
210        {
211            // object is not in view
212            aimMarker_->hide();
213
214            if (!wasOutOfView_)
215            {
216                navMarker_->setMaterialName("Orxonox/NavArrows");
217                wasOutOfView_ = true;
218            }
219
220            if (pos.x < pos.y)
221            {
222                if (pos.y > -pos.x)
223                {
224                    // up
225                    float position = pos.x / pos.y + 1.0;
226                    navMarker_->setPosition((position - navMarker_->getWidth()) * 0.5, 0.0);
227                    navMarker_->setUV(0.5, 0.0, 1.0, 0.5);
228                    navText_->setLeft((position - textLength) * 0.5);
229                    navText_->setTop(navMarker_->getHeight());
230                }
231                else
232                {
233                    // left
234                    float position = pos.y / pos.x + 1.0;
235                    navMarker_->setPosition(0.0, (position - navMarker_->getWidth()) * 0.5);
236                    navMarker_->setUV(0.0, 0.0, 0.5, 0.5);
237                    navText_->setLeft(navMarker_->getWidth() + 0.01);
238                    navText_->setTop((position - navText_->getCharHeight()) * 0.5);
239                }
240            }
241            else
242            {
243                if (pos.y < -pos.x)
244                {
245                    // down
246                    float position = -pos.x / pos.y + 1.0;
247                    navMarker_->setPosition((position - navMarker_->getWidth()) * 0.5, 1.0 - navMarker_->getHeight());
248                    navMarker_->setUV(0.0, 0.5, 0.5, 1.0);
249                    navText_->setLeft((position - textLength) * 0.5);
250                    navText_->setTop(1.0 - navMarker_->getHeight() - navText_->getCharHeight());
251                }
252                else
253                {
254                    // right
255                    float position = -pos.y / pos.x + 1.0;
256                    navMarker_->setPosition(1.0 - navMarker_->getWidth(), (position - navMarker_->getHeight()) * 0.5);
257                    navMarker_->setUV(0.5, 0.5, 1.0, 1.0);
258                    navText_->setLeft(1.0 - navMarker_->getWidth() - textLength - 0.01);
259                    navText_->setTop((position - navText_->getCharHeight()) * 0.5);
260                }
261            }
262        }
263        else
264        {
265            // object is in view
266
267            Vector3 aimpos = transformationMatrix * getPredictedPosition(SpaceShip::getLocalShip()->getPosition(),
268                    Projectile::getSpeed(), focus_->getPosition(), focus_->getOrientedVelocity());
269
270            if (wasOutOfView_)
271            {
272                navMarker_->setMaterialName("Orxonox/NavTDC");
273                wasOutOfView_ = false;
274            }
275
276            // object is in view
277            navMarker_->setUV(0.0, 0.0, 1.0, 1.0);
278            navMarker_->setLeft((pos.x + 1.0 - navMarker_->getWidth()) * 0.5);
279            navMarker_->setTop((-pos.y + 1.0 - navMarker_->getHeight()) * 0.5);
280
281            aimMarker_->show();
282            aimMarker_->setLeft((aimpos.x + 1.0 - aimMarker_->getWidth()) * 0.5);
283            aimMarker_->setTop((-aimpos.y + 1.0 - aimMarker_->getHeight()) * 0.5);
284
285            navText_->setLeft((pos.x + 1.0 + navMarker_->getWidth()) * 0.5);
286            navText_->setTop((-pos.y + 1.0 + navMarker_->getHeight()) * 0.5);
287        }
288    }
289
290    void HUDNavigation::cycleFocus()
291    {
292        if (!focus_)
293        {
294            // Get closest object
295            float distance = (unsigned int) -1;
296            Vector3 shipPos = SpaceShip::getLocalShip()->getPosition();
297            it_ = HUDRadar::getInstance().getRadarObjects().begin();
298
299            for (std::list<RadarObject*>::iterator it = HUDRadar::getInstance().getRadarObjects().begin(); it != HUDRadar::getInstance().getRadarObjects().end(); ++it)
300            {
301                float newdist = (*it)->getPosition().squaredDistance(shipPos);
302                if (newdist < distance)
303                {
304                    distance = newdist;
305                    it_ = it;
306                }
307            }
308
309            if (it_ != HUDRadar::getInstance().getRadarObjects().end())
310            {
311                focus_ = *it_;
312
313                // move the focused object to the begin of the list, so we will iterate through all other objects when cycling
314                HUDRadar::getInstance().getRadarObjects().erase(it_);
315                HUDRadar::getInstance().getRadarObjects().insert(HUDRadar::getInstance().getRadarObjects().begin(), focus_);
316                it_ = HUDRadar::getInstance().getRadarObjects().begin();
317            }
318        }
319        else if (it_ != HUDRadar::getInstance().getRadarObjects().end())
320        {
321            focus_->resetMaterial();
322            ++it_;
323            if (it_ != HUDRadar::getInstance().getRadarObjects().end())
324                focus_ = *it_;
325            else
326                focus_ = 0;
327        }
328        else
329        {
330            focus_ = 0;
331        }
332        updateFocus();
333    }
334
335    void HUDNavigation::updateFocus()
336    {
337        if (focus_)
338        {
339            overlay_->show();
340            focus_->setColour(ColourValue::White);
341        }
342        else
343        {
344            overlay_->hide();
345        }
346    }
347
348    void HUDNavigation::releaseFocus()
349    {
350        this->focus_ = 0;
351        this->updateFocus();
352    }
353
354    float HUDNavigation::getDist2Focus() const
355    {
356        if (focus_)
357            return (focus_->getPosition() - SpaceShip::getLocalShip()->getPosition()).length();
358        else
359            return 0;
360    }
361
362    /**
363    @brief Overridden method of OrxonoxOverlay. Usually the entire overlay
364           scales with scale(). Here we obviously have to adjust this.
365    */
366    void HUDNavigation::sizeChanged()
367    {
368        // use size to compensate for apspect ratio if enabled.
369        float xScale = this->getSize().x;
370        float yScale = this->getSize().y;
371        if (this->navMarker_)
372            navMarker_->setDimensions(navMarkerSize_ * xScale, navMarkerSize_ * yScale);
373        if (this->aimMarker_)
374            aimMarker_->setDimensions(aimMarkerSize_ * xScale, aimMarkerSize_ * yScale);
375        if (this->navText_)
376            navText_->setCharHeight(navText_->getCharHeight() * yScale);
377    }
378
379    /*static*/ HUDNavigation& HUDNavigation::getInstance()
380    {
381        assert(instance_s);
382        return *instance_s;
383    }
384
385    /*static*/ void HUDNavigation::cycleNavigationFocus()
386    {
387        // avoid using getInstance because of the assert().
388        // User might call this fuction even if HUDNavigation doesn't exist.
389        if (instance_s)
390            instance_s->cycleFocus();
391    }
392
393    /*static*/ void HUDNavigation::releaseNavigationFocus()
394    {
395        // avoid using getInstance because of the assert().
396        // User might call this fuction even if HUDNavigation doesn't exist.
397        if (instance_s)
398            instance_s->releaseFocus();
399    }
400}
Note: See TracBrowser for help on using the repository browser.