Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/modules/overlays/hud/HUDNavigation.cc @ 10471

Last change on this file since 10471 was 10294, checked in by landauf, 10 years ago

made projectiles slower (and all have the same speed now). makes it possible to dodge a projectile

  • Property svn:eol-style set to native
File size: 31.8 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
[9526]39#include <typeinfo>
40
[1614]41#include "util/Math.h"
[1616]42#include "util/Convert.h"
[9526]43#include "core/command/ConsoleCommand.h"
[1616]44#include "core/CoreIncludes.h"
45#include "core/XMLPort.h"
[6417]46#include "CameraManager.h"
[5929]47#include "Scene.h"
[5735]48#include "Radar.h"
[6417]49#include "graphics/Camera.h"
50#include "controllers/HumanController.h"
51#include "worldentities/pawns/Pawn.h"
[7163]52#include "worldentities/WorldEntity.h"
[9667]53#include "core/config/ConfigValueIncludes.h"
[7163]54#include "tools/TextureGenerator.h"
55// #include <boost/bind/bind_template.hpp>
[1393]56
[7163]57
[1393]58namespace orxonox
59{
[9526]60
61    SetConsoleCommand("HUDNavigation","selectClosest", &HUDNavigation::selectClosestTarget).addShortcut().keybindMode(KeybindMode::OnPress);
62    SetConsoleCommand("HUDNavigation","selectNext", &HUDNavigation::selectNextTarget).addShortcut().keybindMode(KeybindMode::OnPress);
63
64    static bool compareDistance(std::pair<RadarViewable*, unsigned int> a,
65            std::pair<RadarViewable*, unsigned int> b)
[9348]66    {
67        return a.second < b.second;
68    }
[9667]69    RegisterClass ( HUDNavigation );
[2087]70
[9526]71    HUDNavigation* HUDNavigation::localHUD_s = 0;
72
[9667]73    HUDNavigation::HUDNavigation(Context* context) :
74        OrxonoxOverlay(context)
[9348]75    {
[9939]76        RegisterObject(HUDNavigation);
77        this->setConfigValues();
[2087]78
[9348]79        // Set default values
80        this->setFont("Monofur");
81        this->setTextSize(0.05f);
[9526]82        this->setNavMarkerSize(0.03f);
83        this->setAimMarkerSize(0.02f);
[10258]84        this->setHealthMarkerSize(0.06f);
85        this->setHealthLevelMarkerSize(0.06f);
[9526]86
[9348]87        this->setDetectionLimit(10000.0f);
[10294]88        this->currentMunitionSpeed_ = 750.0f;
[9526]89
90        this->closestTarget_ = true;
91        this->nextTarget_ = false;
92        HUDNavigation::localHUD_s = this;
[9348]93    }
[2087]94
[9348]95    HUDNavigation::~HUDNavigation()
96    {
97        if (this->isInitialized())
98        {
99            for (std::map<RadarViewable*, ObjectInfo>::iterator it = this->activeObjectList_.begin(); it != this->activeObjectList_.end();)
[9526]100            removeObject((it++)->first);
[9348]101        }
102        this->sortedObjectList_.clear();
103    }
[2087]104
[9348]105    void HUDNavigation::setConfigValues()
106    {
107        SetConfigValue(markerLimit_, 3);
108        SetConfigValue(showDistance_, false);
109    }
[2087]110
[9348]111    void HUDNavigation::XMLPort(Element& xmlelement, XMLPort::Mode mode)
[7163]112    {
[9348]113        SUPER(HUDNavigation, XMLPort, xmlelement, mode);
[2087]114
[9526]115        XMLPortParam(HUDNavigation, "font", setFont, getFont, xmlelement, mode);
116        XMLPortParam(HUDNavigation, "textSize", setTextSize, getTextSize, xmlelement, mode);
117        XMLPortParam(HUDNavigation, "navMarkerSize", setNavMarkerSize, getNavMarkerSize, xmlelement, mode);
[9348]118        XMLPortParam(HUDNavigation, "detectionLimit", setDetectionLimit, getDetectionLimit, xmlelement, mode);
[9526]119        XMLPortParam(HUDNavigation, "aimMarkerSize", setAimMarkerSize, getAimMarkerSize, xmlelement, mode);
[10258]120        XMLPortParam(HUDNavigation, "healthMarkerSize", setHealthMarkerSize, getHealthMarkerSize, xmlelement, mode);
121        XMLPortParam(HUDNavigation, "healthLevelMarkerSize", setHealthLevelMarkerSize, getHealthLevelMarkerSize, xmlelement, mode);
122
[1393]123    }
124
[9348]125    void HUDNavigation::setFont(const std::string& font)
126    {
127        const Ogre::ResourcePtr& fontPtr = Ogre::FontManager::getSingleton().getByName(font);
128        if (fontPtr.isNull())
129        {
130            orxout(internal_warning) << "HUDNavigation: Font '" << font << "' not found" << endl;
131            return;
132        }
133        this->fontName_ = font;
134        for (std::map<RadarViewable*, ObjectInfo>::iterator it = this->activeObjectList_.begin(); it != this->activeObjectList_.end(); ++it)
135        {
136            if (it->second.text_ != NULL)
[10292]137                it->second.text_->setFontName(this->fontName_);
[9348]138        }
139    }
[1564]140
[9348]141    const std::string& HUDNavigation::getFont() const
[1590]142    {
[9348]143        return this->fontName_;
[1590]144    }
[9348]145
146    void HUDNavigation::setTextSize(float size)
[1590]147    {
[9348]148        if (size <= 0.0f)
149        {
150            orxout(internal_warning) << "HUDNavigation: Negative font size not allowed" << endl;
151            return;
152        }
153        this->textSize_ = size;
154        for (std::map<RadarViewable*, ObjectInfo>::iterator it = this->activeObjectList_.begin(); it!=this->activeObjectList_.end(); ++it)
155        {
156            if (it->second.text_)
[10292]157                it->second.text_->setCharHeight(size);
[9348]158        }
[1590]159    }
160
[9348]161    float HUDNavigation::getTextSize() const
[1590]162    {
[9348]163        return this->textSize_;
[1590]164    }
[9348]165
166    float HUDNavigation::getArrowSizeX(int dist) const
[7163]167    {
[9348]168        if (dist < 600)
[9526]169        dist = 600;
[9348]170        return this->getActualSize().x * 900 * this->navMarkerSize_ / dist;
[7163]171    }
[1590]172
[9348]173    float HUDNavigation::getArrowSizeY(int dist) const
[1590]174    {
[9348]175        if (dist < 600)
[9526]176        dist = 600;
[9348]177        return this->getActualSize().y * 900 * this->navMarkerSize_ / dist;
[1590]178    }
179
[9348]180    void HUDNavigation::tick(float dt)
[1590]181    {
[9348]182        SUPER(HUDNavigation, tick, dt);
[1400]183
[9348]184        Camera* cam = CameraManager::getInstance().getActiveCamera();
185        if (cam == NULL)
[9526]186        return;
[9348]187        const Matrix4& camTransform = cam->getOgreCamera()->getProjectionMatrix() * cam->getOgreCamera()->getViewMatrix();
[1399]188
[9348]189        for (std::list<std::pair<RadarViewable*, unsigned int> >::iterator listIt = this->sortedObjectList_.begin(); listIt != this->sortedObjectList_.end(); ++listIt)
[9526]190        listIt->second = (int)((listIt->first->getRVWorldPosition() - HumanController::getLocalControllerSingleton()->getControllableEntity()->getWorldPosition()).length() + 0.5f);
[1564]191
[9348]192        this->sortedObjectList_.sort(compareDistance);
[9016]193
[9348]194        unsigned int markerCount = 0;
195        bool closeEnough = false; // only display objects that are close enough to be relevant for the player
[1399]196
[9526]197        // if the selected object doesn't exist any more or is now out of range select the closest object
198        std::map<RadarViewable*, ObjectInfo>::iterator selectedActiveObject = this->activeObjectList_.find(this->selectedTarget_);
199        if(selectedActiveObject == this->activeObjectList_.end())
200        {
201            this->closestTarget_ = true;
202        }
203        else if(this->detectionLimit_ < (this->selectedTarget_->getRVWorldPosition() - HumanController::getLocalControllerSingleton()->getControllableEntity()->getWorldPosition()).length() + 0.5f)
204        {
205            this->closestTarget_ = true;
206            selectedActiveObject->second.selected_ = false;
207        }
208
209        bool nextHasToBeSelected = false;
210
[9348]211        for (std::list<std::pair<RadarViewable*, unsigned int> >::iterator listIt = this->sortedObjectList_.begin(); listIt != this->sortedObjectList_.end(); ++markerCount, ++listIt)
212        {
[10258]213
[9348]214            std::map<RadarViewable*, ObjectInfo>::iterator it = this->activeObjectList_.find(listIt->first);
215            closeEnough = listIt->second < this->detectionLimit_;
216            // display radarviewables on HUD if the marker limit and max-distance is not exceeded
[9526]217            if (markerCount < this->markerLimit_ && (closeEnough || this->detectionLimit_ < 0))
[1580]218            {
[9348]219                // Get Distance to HumanController and save it in the TextAreaOverlayElement.
220                int dist = listIt->second;
221                float textLength = 0.0f;
[1590]222
[9348]223                if (this->showDistance_)
[1580]224                {
[9348]225                    //display distance next to cursor
226                    it->second.text_->setCaption(multi_cast<std::string>(dist));
227                    textLength = multi_cast<std::string>(dist).size() * it->second.text_->getCharHeight() * 0.3f;
[1399]228                }
[9348]229                else
230                {
231                    //display name next to cursor
232                    it->second.text_->setCaption(it->first->getRadarName());
233                    textLength = it->first->getRadarName().size() * it->second.text_->getCharHeight() * 0.3f;
234                }
[7163]235
[9526]236                // select the object that aim-assistant indicates
237                if(this->closestTarget_)
238                // select the closest object
239                {
240                    if(listIt == this->sortedObjectList_.begin())
241                    {
242                        it->second.selected_ = true;
243                        this->selectedTarget_ = it->first;
244                    }
245                    else if(it->second.selected_)
246                    {
247                        it->second.selected_ = false;
248                    }
249
250                }
251                else if(this->nextTarget_)
252                // select the next object in sortedObjectList
253                {
254                    if(nextHasToBeSelected){
255                        it->second.selected_ = true;
256                        this->selectedTarget_ = it->first;
257                        nextHasToBeSelected = false;
258                    }
259                    else if(it->second.selected_)
260                    {
261                        nextHasToBeSelected = true;
262                        it->second.selected_ = false;
263
264                        // check if there's a next object
265                        listIt++;
266                        if(listIt != this->sortedObjectList_.end())
267                        {
268                            // and if the marker limit and max-distance are not exceeded for it
269                            if (markerCount + 1 >= this->markerLimit_ ||
270                                    (listIt->second > this->detectionLimit_ && detectionLimit_ >= 0))
271                            {
272                                // otherwise select the closest object
273                                this->activeObjectList_.find(this->sortedObjectList_.begin()->first)->second.selected_ = true;
274                                this->selectedTarget_ = it->first;
275                                nextHasToBeSelected = false;
276                            }
277                        }
278                        listIt--;
279                    }
280                }
281
282
[10258]283
284
[9348]285                // Transform to screen coordinates
286                Vector3 pos = camTransform * it->first->getRVWorldPosition();
[9016]287
[9348]288                bool outOfView = true;
289                if (pos.z > 1.0)
290                {
291                    // z > 1.0 means that the object is behind the camera
292                    outOfView = true;
293                    // we have to switch all coordinates (if you don't know why,
294                    // try linear algebra lectures, because I can't explain..)
295                    pos.x = -pos.x;
296                    pos.y = -pos.y;
297                }
298                else
299                    outOfView = pos.x < -1.0 || pos.x > 1.0 || pos.y < -1.0 || pos.y > 1.0;
[9016]300
[9348]301                if (outOfView)
[7163]302                {
[9348]303                    // Object is not in view
304
305                    // Change material only if outOfView changed
306                    if (!it->second.wasOutOfView_)
[7163]307                    {
[10258]308                        it->second.health_->hide();
309                        it->second.healthLevel_->hide();
[9348]310                        it->second.panel_->setMaterialName(TextureGenerator::getMaterialName("arrows.png", it->first->getRadarObjectColour()));
311                        it->second.wasOutOfView_ = true;
[9526]312                        it->second.target_->hide();
[7163]313                    }
[9348]314
315                    //float xDistScale = this->getActualSize().x * 1000.0f * this->navMarkerSize_ / dist;
316                    //float yDistScale = this->getActualSize().y * 1000.0f * this->navMarkerSize_ / dist;
317
318                    // Adjust Arrowsize according to distance
319                    it->second.panel_->setDimensions(getArrowSizeX(dist), getArrowSizeY(dist));
320
321                    // Switch between top, bottom, left and right position of the arrow at the screen border
322                    if (pos.x < pos.y)
323                    {
324                        if (pos.y > -pos.x)
325                        {
326                            // Top
327                            float position = pos.x / pos.y + 1.0f;
328                            it->second.panel_->setPosition((position - it->second.panel_->getWidth()) * 0.5f, 0.0f);
329                            it->second.panel_->setUV(0.5f, 0.0f, 1.0f, 0.5f);
330                            it->second.text_->setLeft((position - textLength) * 0.5f);
331                            it->second.text_->setTop(it->second.panel_->getHeight());
332                        }
333                        else
334                        {
335                            // Left
336                            float position = pos.y / pos.x + 1.0f;
337                            it->second.panel_->setPosition(0.0f, (position - it->second.panel_->getWidth()) * 0.5f);
338                            it->second.panel_->setUV(0.0f, 0.0f, 0.5f, 0.5f);
339                            it->second.text_->setLeft(it->second.panel_->getWidth() + 0.01f);
340                            it->second.text_->setTop((position - it->second.text_->getCharHeight()) * 0.5f);
341                        }
342                    }
[7163]343                    else
344                    {
[9348]345                        if (pos.y < -pos.x)
346                        {
347                            // Bottom
348                            float position = -pos.x / pos.y + 1.0f;
349                            it->second.panel_->setPosition((position - it->second.panel_->getWidth()) * 0.5f, 1.0f - it->second.panel_->getHeight());
350                            it->second.panel_->setUV(0.0f, 0.5f, 0.5f, 1.0f );
351                            it->second.text_->setLeft((position - textLength) * 0.5f);
352                            it->second.text_->setTop(1.0f - it->second.panel_->getHeight() - it->second.text_->getCharHeight());
353                        }
354                        else
355                        {
356                            // Right
357                            float position = -pos.y / pos.x + 1.0f;
358                            it->second.panel_->setPosition(1.0f - it->second.panel_->getWidth(), (position - it->second.panel_->getHeight()) * 0.5f);
359                            it->second.panel_->setUV(0.5f, 0.5f, 1.0f, 1.0f);
360                            it->second.text_->setLeft(1.0f - it->second.panel_->getWidth() - textLength - 0.01f);
361                            it->second.text_->setTop((position - it->second.text_->getCharHeight()) * 0.5f);
362                        }
[7163]363                    }
364                }
[1580]365                else
366                {
[9348]367                    // Object is in view
[7163]368
[10258]369
370
371
372                    //calculate the health of the actual selected radarViewable (relativHealthScale: while (0) is no health left, (1) is the initial health)
373                    Pawn* pawnPtr = (Pawn*) (it->first->getWorldEntity());
374                    float health = pawnPtr->getHealth();
375                    float initHealth = pawnPtr->getMaxHealth();
376                    float relativHealthScale = health/initHealth;
377
378                    //integer values from 0 to 10 (0 is no health and 10 is full health)
379                    int discreteHealthScale = (int)(10*relativHealthScale);
380
381                    //calculate the HealthLevel (= OponentLevel or Strength) there are 5 Levels
382                    //Level 1, Level 2,... , Level 5
383                    int HealthLevel = 1;
384
385                    if(initHealth < 200)
386                        HealthLevel = 1;
387                    if(200 <= initHealth && initHealth < 500)
388                        HealthLevel = 2;
389                    if(500 <= initHealth && initHealth < 1000)
390                        HealthLevel = 3;
391                    if(1000 <= initHealth && initHealth < 2500)
392                        HealthLevel = 4;
393                    if(2500 <= initHealth)
394                        HealthLevel = 5;
395
396
397
[9348]398                    // Change material only if outOfView changed
399                    if (it->second.wasOutOfView_)
[7163]400                    {
[9348]401                        //it->second.panel_->setMaterialName("Orxonox/NavTDC");
402                        it->second.panel_->setMaterialName(TextureGenerator::getMaterialName("tdc.png", it->first->getRadarObjectColour()));
403                        it->second.panel_->setDimensions(this->navMarkerSize_ * this->getActualSize().x, this->navMarkerSize_ * this->getActualSize().y);
[9526]404                        it->second.target_->setDimensions(this->aimMarkerSize_ * this->getActualSize().x, this->aimMarkerSize_ * this->getActualSize().y);
[10258]405
406
407                        //it->second.health_->setMaterialName(TextureGenerator::getMaterialName("bar2_1.png", it->first->getRadarObjectColour()));
408                        it->second.health_->setMaterialName(TextureGenerator::getMaterialName("barSquare.png", it->first->getRadarObjectColour()));
409                        it->second.health_->setDimensions(this->healthMarkerSize_ * this->getActualSize().x , 0.75f*this->healthMarkerSize_ * this->getActualSize().y);
[9348]410                        it->second.wasOutOfView_ = false;
[10258]411
412                        // because as soon as relative health drops below 10% (0.1) the descrete value is 0 but as long as the
413                        // spaceship is still intact there should be at least one part of the bar left.
414                        if(1<=discreteHealthScale){
415                            it->second.health_->setTiling((float)discreteHealthScale , 1 ,0);
416                            it->second.health_->setDimensions(this->healthMarkerSize_ * this->getActualSize().x *0.1f*discreteHealthScale, 0.75f*this->healthMarkerSize_ * this->getActualSize().y);
417                        }
418
419
420
421                        //healthLevel
422                        it->second.healthLevel_->setMaterialName(TextureGenerator::getMaterialName("barSquare.png", it->first->getRadarObjectColour()));
423                        it->second.healthLevel_->setDimensions(this->healthLevelMarkerSize_ * this->getActualSize().x , 0.75f*this->healthLevelMarkerSize_ * this->getActualSize().y);
424                        it->second.wasOutOfView_ = false;
425                        it->second.healthLevel_->setTiling((float)HealthLevel , 1 ,0);
426                        it->second.healthLevel_->setDimensions(this->healthLevelMarkerSize_ * this->getActualSize().x *0.1f*HealthLevel, 0.25f*this->healthLevelMarkerSize_ * this->getActualSize().y);
[7163]427                    }
[9348]428
[10258]429
430
431                    // sets Position and Dimensions (amount) health
432                    it->second.health_->setUV(0.0f, 0.0f, 1.0f, 1.0f);
433                    it->second.health_->setLeft((pos.x + 0.975f - it->second.panel_->getWidth()) * 0.5f);
434                    it->second.health_->setTop((-pos.y + 1.04f - it->second.panel_->getHeight()) * 0.5f);
435
436
437                    // because as soon as relative health drops below 10% (0.1) the descrete value is 0 but as long as the
438                    // spaceship is still intact there should be at least one part of the bar left.
439                    if(1<=discreteHealthScale){
440                    it->second.health_->setTiling((float)discreteHealthScale , 1 ,0);
441                    it->second.health_->setDimensions(this->healthMarkerSize_ * this->getActualSize().x *0.1f*discreteHealthScale, 0.75f*this->healthMarkerSize_ * this->getActualSize().y);
442                    }
443
444
445                    //sets Position and Dimensions (level) of healthLevel
446                    it->second.healthLevel_->setMaterialName(TextureGenerator::getMaterialName("barSquare.png", it->first->getRadarObjectColour()));
447                    it->second.healthLevel_->setUV(0.0f, 0.0f, 1.0f, 1.0f);
448                    it->second.healthLevel_->setLeft((pos.x + 0.975f - it->second.panel_->getWidth()) * 0.5f);
449                    it->second.healthLevel_->setTop((-pos.y + 1.125f - it->second.panel_->getHeight()) * 0.5f);
450
451                    it->second.healthLevel_->setTiling((float)HealthLevel , 1 ,0);
452                    it->second.healthLevel_->setDimensions(this->healthLevelMarkerSize_ * this->getActualSize().x *0.1f*HealthLevel, 0.25f*this->healthLevelMarkerSize_ * this->getActualSize().y);
453
454
[9348]455                    // Position marker
456                    it->second.panel_->setUV(0.0f, 0.0f, 1.0f, 1.0f);
457                    it->second.panel_->setLeft((pos.x + 1.0f - it->second.panel_->getWidth()) * 0.5f);
458                    it->second.panel_->setTop((-pos.y + 1.0f - it->second.panel_->getHeight()) * 0.5f);
459
460                    // Position text
461                    it->second.text_->setLeft((pos.x + 1.0f + it->second.panel_->getWidth()) * 0.5f);
462                    it->second.text_->setTop((-pos.y + 1.0f + it->second.panel_->getHeight()) * 0.5f);
[9526]463
[10258]464
465
466
[9526]467                    // Make sure the overlays are shown
[10258]468                    it->second.health_->show();
469                    it->second.healthLevel_->show();
[9526]470                    it->second.panel_->show();
471                    it->second.text_->show();
472
473                    // Target marker
474                    const Pawn* pawn = dynamic_cast<const Pawn*>(it->first->getWorldEntity());
475                    /* Pawn* humanPawn = HumanController::getLocalControllerEntityAsPawn();*/
476                    if(!it->second.selected_
477                            || it->first->getRVVelocity().squaredLength() == 0
478                            || pawn == NULL
479                            /* TODO : improve getTeam in such a way that it works
480                             * || humanPawn == NULL
481                             * || pawn->getTeam() == humanPawn->getTeam()*/)
482                    {
483                        // don't show marker for not selected enemies nor if the selected doesn't move
484                        it->second.target_->hide();
485                    }
486                    else // object is selected and moves
487                    {
488                        // get the aim position
[10291]489                        const Vector3& targetPos = this->toAimPosition(it->first);
[9526]490                        // Transform to screen coordinates
[10291]491                        Vector3 screenPos = camTransform * targetPos;
[9526]492                        // Check if the target marker is in view too
493                        if(screenPos.z > 1 || screenPos.x < -1.0 || screenPos.x > 1.0
494                                || screenPos.y < -1.0 || screenPos.y > 1.0)
495                        {
496                            it->second.target_->hide();
497                        }
498                        else
499                        {
500                            it->second.target_->setLeft((screenPos.x + 1.0f - it->second.target_->getWidth()) * 0.5f);
501                            it->second.target_->setTop((-screenPos.y + 1.0f - it->second.target_->getHeight()) * 0.5f);
502                            it->second.target_->show();
503                        }
504                    }
505
[1411]506                }
507            }
[9348]508            else // do not display on HUD
[9526]509
[1580]510            {
[10258]511                it->second.health_->hide();
512                it->second.healthLevel_->hide();
[9348]513                it->second.panel_->hide();
514                it->second.text_->hide();
[9526]515                it->second.target_->hide();
[9348]516            }
517        }
[9526]518
519        this->closestTarget_ = false;
520        this->nextTarget_ = false;
[9348]521    }
[7163]522
[9348]523    /** Overridden method of OrxonoxOverlay.
[9526]524     @details
525     Usually the entire overlay scales with scale().
526     Here we obviously have to adjust this.
527     */
[9348]528    void HUDNavigation::sizeChanged()
529    {
530        // Use size to compensate for aspect ratio if enabled.
531        float xScale = this->getActualSize().x;
532        float yScale = this->getActualSize().y;
[7163]533
[9348]534        for (std::map<RadarViewable*, ObjectInfo>::iterator it = this->activeObjectList_.begin(); it != this->activeObjectList_.end(); ++it)
[1580]535        {
[10258]536            if (it->second.health_ != NULL)
537                it->second.health_->setDimensions(this->healthMarkerSize_ * xScale, this->healthMarkerSize_ * yScale);
538            if (it->second.healthLevel_ != NULL)
539                it->second.healthLevel_->setDimensions(this->healthLevelMarkerSize_ * xScale, this->healthLevelMarkerSize_ * yScale);
[9348]540            if (it->second.panel_ != NULL)
541                it->second.panel_->setDimensions(this->navMarkerSize_ * xScale, this->navMarkerSize_ * yScale);
542            if (it->second.text_ != NULL)
[10292]543                it->second.text_->setCharHeight(this->textSize_ * yScale);
[9526]544            if (it->second.target_ != NULL)
545                it->second.target_->setDimensions(this->aimMarkerSize_ * xScale, this->aimMarkerSize_ * yScale);
[7163]546        }
547    }
[1566]548
[9348]549    void HUDNavigation::addObject(RadarViewable* object)
[7163]550    {
[9348]551        if (showObject(object) == false)
[9526]552        return;
[7163]553
[9348]554        if (this->activeObjectList_.size() >= this->markerLimit_)
[9526]555        if (object == NULL)
556        return;
[7163]557
[9348]558        // Object hasn't been added yet (we know that)
559        assert(this->activeObjectList_.find(object) == this->activeObjectList_.end());
[7163]560
[9348]561        // Scales used for dimensions and text size
562        float xScale = this->getActualSize().x;
563        float yScale = this->getActualSize().y;
[7163]564
[9348]565        // Create everything needed to display the object on the radar and add it to the map
[7163]566
[10258]567        // Create health
568        Ogre::PanelOverlayElement* health = static_cast<Ogre::PanelOverlayElement*>( Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", "HUDNavigation_healthMarker_" + getUniqueNumberString()));
569        //panel->setMaterialName("Orxonox/NavTDC");
570        health->setMaterialName(TextureGenerator::getMaterialName("barSquare.png", object->getRadarObjectColour()));
571        health->setDimensions(this->healthMarkerSize_ * xScale, this->healthMarkerSize_ * yScale);
572        //panel->setColour(object->getRadarObjectColour());
573
574        // Create healthLevel
575        Ogre::PanelOverlayElement* healthLevel = static_cast<Ogre::PanelOverlayElement*>( Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", "HUDNavigation_healthLevelMarker_" + getUniqueNumberString()));
576        //panel->setMaterialName("Orxonox/NavTDC");
577        health->setMaterialName(TextureGenerator::getMaterialName("barSquare.png", object->getRadarObjectColour()));
578        health->setDimensions(this->healthLevelMarkerSize_ * xScale, this->healthLevelMarkerSize_ * yScale);
579
580
[9348]581        // Create arrow/marker
582        Ogre::PanelOverlayElement* panel = static_cast<Ogre::PanelOverlayElement*>( Ogre::OverlayManager::getSingleton()
[9526]583                .createOverlayElement("Panel", "HUDNavigation_navMarker_" + getUniqueNumberString()));
[9348]584        //panel->setMaterialName("Orxonox/NavTDC");
585        panel->setMaterialName(TextureGenerator::getMaterialName("tdc.png", object->getRadarObjectColour()));
586        panel->setDimensions(this->navMarkerSize_ * xScale, this->navMarkerSize_ * yScale);
587        //panel->setColour(object->getRadarObjectColour());
[7163]588
[9526]589        // Create target marker
590        Ogre::PanelOverlayElement* target = static_cast<Ogre::PanelOverlayElement*>(Ogre::OverlayManager::getSingleton()
591                    .createOverlayElement("Panel", "HUDNavigation_targetMarker_" + getUniqueNumberString()));
592        target->setMaterialName(TextureGenerator::getMaterialName("target.png", object->getRadarObjectColour()));
593        target->setDimensions(this->aimMarkerSize_ * xScale, this->aimMarkerSize_ * yScale);
594
595        // Create text
[9348]596        Ogre::TextAreaOverlayElement* text = static_cast<Ogre::TextAreaOverlayElement*>( Ogre::OverlayManager::getSingleton()
[9526]597                .createOverlayElement("TextArea", "HUDNavigation_navText_" + getUniqueNumberString()));
[9348]598        text->setFontName(this->fontName_);
[10292]599        text->setCharHeight(this->textSize_ * yScale);
[9348]600        text->setColour(object->getRadarObjectColour());
[7163]601
[10258]602        health->hide();
603        healthLevel->hide();
[9348]604        panel->hide();
[9526]605        target->hide();
[9348]606        text->hide();
[7163]607
[9526]608        ObjectInfo tempStruct =
[10258]609        {   health, healthLevel, panel, target, text, false, false, false};
[9348]610        this->activeObjectList_[object] = tempStruct;
[7163]611
[10258]612        this->background_->addChild(health);
613        this->background_->addChild(healthLevel);
[9348]614        this->background_->addChild(panel);
[9526]615        this->background_->addChild(target);
[9348]616        this->background_->addChild(text);
[7163]617
[9348]618        this->sortedObjectList_.push_front(std::make_pair(object, (unsigned int)0));
619    }
[7163]620
[9348]621    void HUDNavigation::removeObject(RadarViewable* viewable)
[1580]622    {
[9348]623        std::map<RadarViewable*, ObjectInfo>::iterator it = this->activeObjectList_.find(viewable);
[7163]624
[9348]625        if (this->activeObjectList_.find(viewable) != this->activeObjectList_.end())
626        {
627            // Detach overlays
[10258]628            this->background_->removeChild(it->second.health_->getName());
629            this->background_->removeChild(it->second.healthLevel_->getName());
[9348]630            this->background_->removeChild(it->second.panel_->getName());
[9526]631            this->background_->removeChild(it->second.target_->getName());
[9348]632            this->background_->removeChild(it->second.text_->getName());
633            // Properly destroy the overlay elements (do not use delete!)
[10258]634            Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.health_);
635            Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.healthLevel_);
[9348]636            Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.panel_);
[9526]637            Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.target_);
[9348]638            Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.text_);
639            // Remove from the list
640            this->activeObjectList_.erase(viewable);
641        }
[7163]642
[9348]643        for (std::list<std::pair<RadarViewable*, unsigned int> >::iterator listIt = this->sortedObjectList_.begin(); listIt != this->sortedObjectList_.end(); ++listIt)
644        {
645            if ((listIt->first) == viewable)
646            {
647                this->sortedObjectList_.erase(listIt);
648                break;
649            }
650        }
[1410]651    }
[1590]652
[9348]653    void HUDNavigation::objectChanged(RadarViewable* viewable)
[1590]654    {
[9348]655        // TODO: niceification neccessary ;)
656        removeObject(viewable);
657        addObject(viewable);
658    }
[7163]659
[9348]660    bool HUDNavigation::showObject(RadarViewable* rv)
661    {
662        if (rv == orxonox_cast<RadarViewable*>(this->getOwner()))
[9526]663        return false;
[9348]664        assert(rv->getWorldEntity());
665        if (rv->getWorldEntity()->isVisible() == false || rv->getRadarVisibility() == false)
[9526]666        return false;
[9348]667        return true;
[1590]668    }
[7163]669
[9348]670    void HUDNavigation::changedOwner()
[7163]671    {
[9348]672        const std::set<RadarViewable*>& respawnObjects = this->getOwner()->getScene()->getRadar()->getRadarObjects();
673        for (std::set<RadarViewable*>::const_iterator it = respawnObjects.begin(); it != respawnObjects.end(); ++it)
674        {
675            if (!(*it)->isHumanShip_)
[9526]676            this->addObject(*it);
[9348]677        }
[7163]678    }
[9526]679
[10291]680    Vector3 HUDNavigation::toAimPosition(RadarViewable* target) const
[9526]681    {
682        Vector3 wePosition = HumanController::getLocalControllerSingleton()->getControllableEntity()->getWorldPosition();
683        Vector3 targetPosition = target->getRVWorldPosition();
684        Vector3 targetSpeed = target->getRVVelocity();
685
[10291]686        return getPredictedPosition(wePosition, this->currentMunitionSpeed_, targetPosition, targetSpeed);
[9526]687    }
688
689    void HUDNavigation::selectClosestTarget()
690    {
691        if(HUDNavigation::localHUD_s)
692        {
693            HUDNavigation::localHUD_s->closestTarget_ = true;
694        }
695    }
696
697    void HUDNavigation::selectNextTarget()
698    {
699        if(HUDNavigation::localHUD_s)
700        {
701            HUDNavigation::localHUD_s->nextTarget_ = true;
702        }
703    }
[7163]704}
Note: See TracBrowser for help on using the repository browser.