Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

merged branch cpp11_v3 back to trunk

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