Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/hudHS14/src/modules/overlays/hud/HUDNavigation.cc @ 10240

Last change on this file since 10240 was 10240, checked in by landauf, 9 years ago

replaced tabs with spaces. no changes in code.

  • Property svn:eol-style set to native
File size: 32.2 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);
[10149]84        this->setHealthMarkerSize(0.06f);
[10163]85        this->setHealthLevelMarkerSize(0.06f);
[9526]86
[9348]87        this->setDetectionLimit(10000.0f);
[9526]88        this->currentMunitionSpeed_ = 2500.0f;
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);
[10122]120        XMLPortParam(HUDNavigation, "healthMarkerSize", setHealthMarkerSize, getHealthMarkerSize, xmlelement, mode);
[10163]121        XMLPortParam(HUDNavigation, "healthLevelMarkerSize", setHealthLevelMarkerSize, getHealthLevelMarkerSize, xmlelement, mode);
[10122]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)
[9526]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_)
[9526]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        {
[10122]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
[10122]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                    {
[10240]308                        it->second.health_->hide();
309                        it->second.healthLevel_->hide();
310                        it->second.panel_->setMaterialName(TextureGenerator::getMaterialName("arrows.png", it->first->getRadarObjectColour()));
[9348]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
[10122]369
370
371
[10240]372                    //calculate the health of the actual selected radarViewable (relativHealthScale: while (0) is no health left, (1) is the initial health)
[10149]373                    Pawn* pawnPtr = (Pawn*) (it->first->getWorldEntity());
374                    float health = pawnPtr->getHealth();
375                    float initHealth = pawnPtr->getMaxHealth();
376                    float relativHealthScale = health/initHealth;
[10122]377
[10163]378                    //integer values from 0 to 10 (0 is no health and 10 is full health)
[10239]379                    int discreteHealthScale = (int)(10*relativHealthScale);
[10143]380
[10163]381                    //calculate the HealthLevel (= OponentLevel or Strength) there are 5 Levels
382                    //Level 1, Level 2,... , Level 5
383                    int HealthLevel = 1;
[10149]384
[10163]385                    if(initHealth < 200)
[10240]386                        HealthLevel = 1;
[10163]387                    if(200 <= initHealth && initHealth < 500)
[10240]388                        HealthLevel = 2;
[10163]389                    if(500 <= initHealth && initHealth < 1000)
[10240]390                        HealthLevel = 3;
[10163]391                    if(1000 <= initHealth && initHealth < 2500)
[10240]392                        HealthLevel = 4;
[10163]393                    if(2500 <= initHealth)
[10240]394                        HealthLevel = 5;
[10149]395
[10163]396
397
[10240]398                    // Change material only if outOfView changed
[9348]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);
[10110]405
[10163]406
[10149]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()));
[10239]409                        it->second.health_->setDimensions(this->healthMarkerSize_ * this->getActualSize().x , 0.75f*this->healthMarkerSize_ * this->getActualSize().y);
[9348]410                        it->second.wasOutOfView_ = false;
[10149]411
[10163]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.
[10149]414                        if(1<=discreteHealthScale){
[10240]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);
[10149]417                        }
[10163]418
419
420
421                        //healthLevel
422                        it->second.healthLevel_->setMaterialName(TextureGenerator::getMaterialName("barSquare.png", it->first->getRadarObjectColour()));
[10239]423                        it->second.healthLevel_->setDimensions(this->healthLevelMarkerSize_ * this->getActualSize().x , 0.75f*this->healthLevelMarkerSize_ * this->getActualSize().y);
[10163]424                        it->second.wasOutOfView_ = false;
425                        it->second.healthLevel_->setTiling((float)HealthLevel , 1 ,0);
[10239]426                        it->second.healthLevel_->setDimensions(this->healthLevelMarkerSize_ * this->getActualSize().x *0.1f*HealthLevel, 0.25f*this->healthLevelMarkerSize_ * this->getActualSize().y);
[7163]427                    }
[9348]428
[10122]429
430
[10163]431                    // sets Position and Dimensions (amount) health
[10122]432                    it->second.health_->setUV(0.0f, 0.0f, 1.0f, 1.0f);
[10143]433                    it->second.health_->setLeft((pos.x + 0.975f - it->second.panel_->getWidth()) * 0.5f);
[10149]434                    it->second.health_->setTop((-pos.y + 1.04f - it->second.panel_->getHeight()) * 0.5f);
[10110]435
436
[10163]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.
[10149]439                    if(1<=discreteHealthScale){
440                    it->second.health_->setTiling((float)discreteHealthScale , 1 ,0);
[10239]441                    it->second.health_->setDimensions(this->healthMarkerSize_ * this->getActualSize().x *0.1f*discreteHealthScale, 0.75f*this->healthMarkerSize_ * this->getActualSize().y);
[10149]442                    }
443
444
[10163]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);
[10149]450
[10163]451                    it->second.healthLevel_->setTiling((float)HealthLevel , 1 ,0);
[10239]452                    it->second.healthLevel_->setDimensions(this->healthLevelMarkerSize_ * this->getActualSize().x *0.1f*HealthLevel, 0.25f*this->healthLevelMarkerSize_ * this->getActualSize().y);
[10163]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
[10163]464
465
466
[9526]467                    // Make sure the overlays are shown
[10110]468                    it->second.health_->show();
[10163]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
489                        Vector3* targetPos = this->toAimPosition(it->first);
490                        // Transform to screen coordinates
491                        Vector3 screenPos = camTransform * (*targetPos);
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                        delete targetPos;
505                    }
506
[1411]507                }
508            }
[9348]509            else // do not display on HUD
[9526]510
[1580]511            {
[10240]512                it->second.health_->hide();
[10163]513                it->second.healthLevel_->hide();
[10240]514                it->second.panel_->hide();
[9348]515                it->second.text_->hide();
[9526]516                it->second.target_->hide();
[9348]517            }
518        }
[9526]519
520        this->closestTarget_ = false;
521        this->nextTarget_ = false;
[9348]522    }
[7163]523
[9348]524    /** Overridden method of OrxonoxOverlay.
[9526]525     @details
526     Usually the entire overlay scales with scale().
527     Here we obviously have to adjust this.
528     */
[9348]529    void HUDNavigation::sizeChanged()
530    {
531        // Use size to compensate for aspect ratio if enabled.
532        float xScale = this->getActualSize().x;
533        float yScale = this->getActualSize().y;
[7163]534
[9348]535        for (std::map<RadarViewable*, ObjectInfo>::iterator it = this->activeObjectList_.begin(); it != this->activeObjectList_.end(); ++it)
[1580]536        {
[10240]537            if (it->second.health_ != NULL)
538                it->second.health_->setDimensions(this->healthMarkerSize_ * xScale, this->healthMarkerSize_ * yScale);
539            if (it->second.healthLevel_ != NULL)
540                it->second.healthLevel_->setDimensions(this->healthLevelMarkerSize_ * xScale, this->healthLevelMarkerSize_ * yScale);
[9348]541            if (it->second.panel_ != NULL)
542                it->second.panel_->setDimensions(this->navMarkerSize_ * xScale, this->navMarkerSize_ * yScale);
543            if (it->second.text_ != NULL)
544                it->second.text_->setCharHeight(it->second.text_->getCharHeight() * yScale);
[9526]545            if (it->second.target_ != NULL)
546                it->second.target_->setDimensions(this->aimMarkerSize_ * xScale, this->aimMarkerSize_ * yScale);
[7163]547        }
548    }
[1566]549
[9348]550    void HUDNavigation::addObject(RadarViewable* object)
[7163]551    {
[9348]552        if (showObject(object) == false)
[9526]553        return;
[7163]554
[9348]555        if (this->activeObjectList_.size() >= this->markerLimit_)
[9526]556        if (object == NULL)
557        return;
[7163]558
[9348]559        // Object hasn't been added yet (we know that)
560        assert(this->activeObjectList_.find(object) == this->activeObjectList_.end());
[7163]561
[9348]562        // Scales used for dimensions and text size
563        float xScale = this->getActualSize().x;
564        float yScale = this->getActualSize().y;
[7163]565
[9348]566        // Create everything needed to display the object on the radar and add it to the map
[10149]567
[10110]568        // Create health
[10163]569        Ogre::PanelOverlayElement* health = static_cast<Ogre::PanelOverlayElement*>( Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", "HUDNavigation_healthMarker_" + getUniqueNumberString()));
570        //panel->setMaterialName("Orxonox/NavTDC");
571        health->setMaterialName(TextureGenerator::getMaterialName("barSquare.png", object->getRadarObjectColour()));
572        health->setDimensions(this->healthMarkerSize_ * xScale, this->healthMarkerSize_ * yScale);
573        //panel->setColour(object->getRadarObjectColour());
[7163]574
[10163]575        // Create healthLevel
576        Ogre::PanelOverlayElement* healthLevel = static_cast<Ogre::PanelOverlayElement*>( Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", "HUDNavigation_healthLevelMarker_" + getUniqueNumberString()));
577        //panel->setMaterialName("Orxonox/NavTDC");
578        health->setMaterialName(TextureGenerator::getMaterialName("barSquare.png", object->getRadarObjectColour()));
579        health->setDimensions(this->healthLevelMarkerSize_ * xScale, this->healthLevelMarkerSize_ * yScale);
[10110]580
[10163]581
[9348]582        // Create arrow/marker
583        Ogre::PanelOverlayElement* panel = static_cast<Ogre::PanelOverlayElement*>( Ogre::OverlayManager::getSingleton()
[9526]584                .createOverlayElement("Panel", "HUDNavigation_navMarker_" + getUniqueNumberString()));
[9348]585        //panel->setMaterialName("Orxonox/NavTDC");
586        panel->setMaterialName(TextureGenerator::getMaterialName("tdc.png", object->getRadarObjectColour()));
587        panel->setDimensions(this->navMarkerSize_ * xScale, this->navMarkerSize_ * yScale);
588        //panel->setColour(object->getRadarObjectColour());
[7163]589
[9526]590        // Create target marker
591        Ogre::PanelOverlayElement* target = static_cast<Ogre::PanelOverlayElement*>(Ogre::OverlayManager::getSingleton()
592                    .createOverlayElement("Panel", "HUDNavigation_targetMarker_" + getUniqueNumberString()));
593        target->setMaterialName(TextureGenerator::getMaterialName("target.png", object->getRadarObjectColour()));
594        target->setDimensions(this->aimMarkerSize_ * xScale, this->aimMarkerSize_ * yScale);
595
596        // Create text
[9348]597        Ogre::TextAreaOverlayElement* text = static_cast<Ogre::TextAreaOverlayElement*>( Ogre::OverlayManager::getSingleton()
[9526]598                .createOverlayElement("TextArea", "HUDNavigation_navText_" + getUniqueNumberString()));
[9348]599        text->setFontName(this->fontName_);
600        text->setCharHeight(text->getCharHeight() * yScale);
601        text->setColour(object->getRadarObjectColour());
[7163]602
[10110]603        health->hide();
[10163]604        healthLevel->hide();
[9348]605        panel->hide();
[9526]606        target->hide();
[9348]607        text->hide();
[7163]608
[9526]609        ObjectInfo tempStruct =
[10163]610        {   health, healthLevel, panel, target, text, false, false, false};
[9348]611        this->activeObjectList_[object] = tempStruct;
[7163]612
[10110]613        this->background_->addChild(health);
[10163]614        this->background_->addChild(healthLevel);
[9348]615        this->background_->addChild(panel);
[9526]616        this->background_->addChild(target);
[9348]617        this->background_->addChild(text);
[7163]618
[9348]619        this->sortedObjectList_.push_front(std::make_pair(object, (unsigned int)0));
620    }
[7163]621
[9348]622    void HUDNavigation::removeObject(RadarViewable* viewable)
[1580]623    {
[9348]624        std::map<RadarViewable*, ObjectInfo>::iterator it = this->activeObjectList_.find(viewable);
[7163]625
[9348]626        if (this->activeObjectList_.find(viewable) != this->activeObjectList_.end())
627        {
628            // Detach overlays
[10240]629            this->background_->removeChild(it->second.health_->getName());
630            this->background_->removeChild(it->second.healthLevel_->getName());
[9348]631            this->background_->removeChild(it->second.panel_->getName());
[9526]632            this->background_->removeChild(it->second.target_->getName());
[9348]633            this->background_->removeChild(it->second.text_->getName());
634            // Properly destroy the overlay elements (do not use delete!)
[10110]635            Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.health_);
[10163]636            Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.healthLevel_);
[9348]637            Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.panel_);
[9526]638            Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.target_);
[9348]639            Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.text_);
640            // Remove from the list
641            this->activeObjectList_.erase(viewable);
642        }
[7163]643
[9348]644        for (std::list<std::pair<RadarViewable*, unsigned int> >::iterator listIt = this->sortedObjectList_.begin(); listIt != this->sortedObjectList_.end(); ++listIt)
645        {
646            if ((listIt->first) == viewable)
647            {
648                this->sortedObjectList_.erase(listIt);
649                break;
650            }
651        }
[1410]652    }
[1590]653
[9348]654    void HUDNavigation::objectChanged(RadarViewable* viewable)
[1590]655    {
[9348]656        // TODO: niceification neccessary ;)
657        removeObject(viewable);
658        addObject(viewable);
659    }
[7163]660
[9348]661    bool HUDNavigation::showObject(RadarViewable* rv)
662    {
663        if (rv == orxonox_cast<RadarViewable*>(this->getOwner()))
[9526]664        return false;
[9348]665        assert(rv->getWorldEntity());
666        if (rv->getWorldEntity()->isVisible() == false || rv->getRadarVisibility() == false)
[9526]667        return false;
[9348]668        return true;
[1590]669    }
[7163]670
[9348]671    void HUDNavigation::changedOwner()
[7163]672    {
[9348]673        const std::set<RadarViewable*>& respawnObjects = this->getOwner()->getScene()->getRadar()->getRadarObjects();
674        for (std::set<RadarViewable*>::const_iterator it = respawnObjects.begin(); it != respawnObjects.end(); ++it)
675        {
676            if (!(*it)->isHumanShip_)
[9526]677            this->addObject(*it);
[9348]678        }
[7163]679    }
[9526]680
681    Vector3* HUDNavigation::toAimPosition(RadarViewable* target) const
682    {
683        Vector3 wePosition = HumanController::getLocalControllerSingleton()->getControllableEntity()->getWorldPosition();
684        Vector3 targetPosition = target->getRVWorldPosition();
685        Vector3 targetSpeed = target->getRVVelocity();
686        Vector3 relativePosition = targetPosition - wePosition; //Vector from attacker to target
687
688        float p_half = relativePosition.dotProduct(targetSpeed)/(targetSpeed.squaredLength() - this->currentMunitionSpeed_ * this->currentMunitionSpeed_);
689        float time1 = -p_half + sqrt(p_half * p_half - relativePosition.squaredLength()/(targetSpeed.squaredLength() - this->currentMunitionSpeed_ * this->currentMunitionSpeed_));
690
691        Vector3* result = new Vector3(targetPosition + targetSpeed * time1);
692        return result;
693    }
694
695    void HUDNavigation::selectClosestTarget()
696    {
697        if(HUDNavigation::localHUD_s)
698        {
699            HUDNavigation::localHUD_s->closestTarget_ = true;
700        }
701    }
702
703    void HUDNavigation::selectNextTarget()
704    {
705        if(HUDNavigation::localHUD_s)
706        {
707            HUDNavigation::localHUD_s->nextTarget_ = true;
708        }
709    }
[7163]710}
Note: See TracBrowser for help on using the repository browser.