Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 12209 was 11795, checked in by landauf, 7 years ago

merged ogre1.9 (including cegui0.8) into new branch

  • 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>
[1410]34
[11795]35#if OGRE_VERSION >= 0x010900
36#   include <Overlay/OgreFontManager.h>
37#   include <Overlay/OgreOverlayManager.h>
38#   include <Overlay/OgreTextAreaOverlayElement.h>
39#   include <Overlay/OgrePanelOverlayElement.h>
40#else
41#   include <OgreFontManager.h>
42#   include <OgreOverlayManager.h>
43#   include <OgreTextAreaOverlayElement.h>
44#   include <OgrePanelOverlayElement.h>
45#endif
46
[9526]47#include <typeinfo>
48
[1614]49#include "util/Math.h"
[1616]50#include "util/Convert.h"
[10624]51#include "core/command/ConsoleCommandIncludes.h"
[1616]52#include "core/CoreIncludes.h"
53#include "core/XMLPort.h"
[6417]54#include "CameraManager.h"
[5929]55#include "Scene.h"
[5735]56#include "Radar.h"
[6417]57#include "graphics/Camera.h"
58#include "controllers/HumanController.h"
59#include "worldentities/pawns/Pawn.h"
[7163]60#include "worldentities/WorldEntity.h"
[9667]61#include "core/config/ConfigValueIncludes.h"
[7163]62#include "tools/TextureGenerator.h"
[1393]63
[7163]64
[1393]65namespace orxonox
66{
[9526]67
68    SetConsoleCommand("HUDNavigation","selectClosest", &HUDNavigation::selectClosestTarget).addShortcut().keybindMode(KeybindMode::OnPress);
69    SetConsoleCommand("HUDNavigation","selectNext", &HUDNavigation::selectNextTarget).addShortcut().keybindMode(KeybindMode::OnPress);
70
71    static bool compareDistance(std::pair<RadarViewable*, unsigned int> a,
72            std::pair<RadarViewable*, unsigned int> b)
[9348]73    {
74        return a.second < b.second;
75    }
[9667]76    RegisterClass ( HUDNavigation );
[2087]77
[11071]78    HUDNavigation* HUDNavigation::localHUD_s = nullptr;
[9526]79
[9667]80    HUDNavigation::HUDNavigation(Context* context) :
81        OrxonoxOverlay(context)
[9348]82    {
[9939]83        RegisterObject(HUDNavigation);
84        this->setConfigValues();
[2087]85
[9348]86        // Set default values
87        this->setFont("Monofur");
88        this->setTextSize(0.05f);
[9526]89        this->setNavMarkerSize(0.03f);
90        this->setAimMarkerSize(0.02f);
[10258]91        this->setHealthMarkerSize(0.06f);
92        this->setHealthLevelMarkerSize(0.06f);
[9526]93
[9348]94        this->setDetectionLimit(10000.0f);
[10294]95        this->currentMunitionSpeed_ = 750.0f;
[9526]96
97        this->closestTarget_ = true;
98        this->nextTarget_ = false;
99        HUDNavigation::localHUD_s = this;
[9348]100    }
[2087]101
[9348]102    HUDNavigation::~HUDNavigation()
103    {
104        if (this->isInitialized())
105        {
106            for (std::map<RadarViewable*, ObjectInfo>::iterator it = this->activeObjectList_.begin(); it != this->activeObjectList_.end();)
[9526]107            removeObject((it++)->first);
[9348]108        }
109        this->sortedObjectList_.clear();
110    }
[2087]111
[9348]112    void HUDNavigation::setConfigValues()
113    {
114        SetConfigValue(markerLimit_, 3);
115        SetConfigValue(showDistance_, false);
116    }
[2087]117
[9348]118    void HUDNavigation::XMLPort(Element& xmlelement, XMLPort::Mode mode)
[7163]119    {
[9348]120        SUPER(HUDNavigation, XMLPort, xmlelement, mode);
[2087]121
[9526]122        XMLPortParam(HUDNavigation, "font", setFont, getFont, xmlelement, mode);
123        XMLPortParam(HUDNavigation, "textSize", setTextSize, getTextSize, xmlelement, mode);
124        XMLPortParam(HUDNavigation, "navMarkerSize", setNavMarkerSize, getNavMarkerSize, xmlelement, mode);
[9348]125        XMLPortParam(HUDNavigation, "detectionLimit", setDetectionLimit, getDetectionLimit, xmlelement, mode);
[9526]126        XMLPortParam(HUDNavigation, "aimMarkerSize", setAimMarkerSize, getAimMarkerSize, xmlelement, mode);
[10258]127        XMLPortParam(HUDNavigation, "healthMarkerSize", setHealthMarkerSize, getHealthMarkerSize, xmlelement, mode);
128        XMLPortParam(HUDNavigation, "healthLevelMarkerSize", setHealthLevelMarkerSize, getHealthLevelMarkerSize, xmlelement, mode);
129
[1393]130    }
131
[9348]132    void HUDNavigation::setFont(const std::string& font)
133    {
134        const Ogre::ResourcePtr& fontPtr = Ogre::FontManager::getSingleton().getByName(font);
135        if (fontPtr.isNull())
136        {
137            orxout(internal_warning) << "HUDNavigation: Font '" << font << "' not found" << endl;
138            return;
139        }
140        this->fontName_ = font;
[11071]141        for (const auto& mapEntry : this->activeObjectList_)
[9348]142        {
[11071]143            if (mapEntry.second.text_ != nullptr)
144                mapEntry.second.text_->setFontName(this->fontName_);
[9348]145        }
146    }
[1564]147
[9348]148    const std::string& HUDNavigation::getFont() const
[1590]149    {
[9348]150        return this->fontName_;
[1590]151    }
[9348]152
153    void HUDNavigation::setTextSize(float size)
[1590]154    {
[9348]155        if (size <= 0.0f)
156        {
157            orxout(internal_warning) << "HUDNavigation: Negative font size not allowed" << endl;
158            return;
159        }
160        this->textSize_ = size;
[11071]161        for (const auto& mapEntry : this->activeObjectList_)
[9348]162        {
[11071]163            if (mapEntry.second.text_)
164                mapEntry.second.text_->setCharHeight(size);
[9348]165        }
[1590]166    }
167
[9348]168    float HUDNavigation::getTextSize() const
[1590]169    {
[9348]170        return this->textSize_;
[1590]171    }
[9348]172
173    float HUDNavigation::getArrowSizeX(int dist) const
[7163]174    {
[9348]175        if (dist < 600)
[9526]176        dist = 600;
[9348]177        return this->getActualSize().x * 900 * this->navMarkerSize_ / dist;
[7163]178    }
[1590]179
[9348]180    float HUDNavigation::getArrowSizeY(int dist) const
[1590]181    {
[9348]182        if (dist < 600)
[9526]183        dist = 600;
[9348]184        return this->getActualSize().y * 900 * this->navMarkerSize_ / dist;
[1590]185    }
186
[9348]187    void HUDNavigation::tick(float dt)
[1590]188    {
[9348]189        SUPER(HUDNavigation, tick, dt);
[1400]190
[9348]191        Camera* cam = CameraManager::getInstance().getActiveCamera();
[11071]192        if (cam == nullptr)
[9526]193        return;
[9348]194        const Matrix4& camTransform = cam->getOgreCamera()->getProjectionMatrix() * cam->getOgreCamera()->getViewMatrix();
[1399]195
[11071]196        for (std::pair<RadarViewable*, unsigned int>& pair : this->sortedObjectList_)
197        pair.second = (int)((pair.first->getRVWorldPosition() - HumanController::getLocalControllerSingleton()->getControllableEntity()->getWorldPosition()).length() + 0.5f);
[1564]198
[9348]199        this->sortedObjectList_.sort(compareDistance);
[9016]200
[9348]201        unsigned int markerCount = 0;
202        bool closeEnough = false; // only display objects that are close enough to be relevant for the player
[1399]203
[9526]204        // if the selected object doesn't exist any more or is now out of range select the closest object
205        std::map<RadarViewable*, ObjectInfo>::iterator selectedActiveObject = this->activeObjectList_.find(this->selectedTarget_);
206        if(selectedActiveObject == this->activeObjectList_.end())
207        {
208            this->closestTarget_ = true;
209        }
210        else if(this->detectionLimit_ < (this->selectedTarget_->getRVWorldPosition() - HumanController::getLocalControllerSingleton()->getControllableEntity()->getWorldPosition()).length() + 0.5f)
211        {
212            this->closestTarget_ = true;
213            selectedActiveObject->second.selected_ = false;
214        }
215
216        bool nextHasToBeSelected = false;
217
[11071]218        for (std::list<std::pair<RadarViewable*, unsigned int>>::iterator listIt = this->sortedObjectList_.begin(); listIt != this->sortedObjectList_.end(); ++markerCount, ++listIt)
[9348]219        {
[10258]220
[9348]221            std::map<RadarViewable*, ObjectInfo>::iterator it = this->activeObjectList_.find(listIt->first);
222            closeEnough = listIt->second < this->detectionLimit_;
223            // display radarviewables on HUD if the marker limit and max-distance is not exceeded
[9526]224            if (markerCount < this->markerLimit_ && (closeEnough || this->detectionLimit_ < 0))
[1580]225            {
[9348]226                // Get Distance to HumanController and save it in the TextAreaOverlayElement.
227                int dist = listIt->second;
228                float textLength = 0.0f;
[1590]229
[9348]230                if (this->showDistance_)
[1580]231                {
[9348]232                    //display distance next to cursor
233                    it->second.text_->setCaption(multi_cast<std::string>(dist));
234                    textLength = multi_cast<std::string>(dist).size() * it->second.text_->getCharHeight() * 0.3f;
[1399]235                }
[9348]236                else
237                {
238                    //display name next to cursor
239                    it->second.text_->setCaption(it->first->getRadarName());
240                    textLength = it->first->getRadarName().size() * it->second.text_->getCharHeight() * 0.3f;
241                }
[7163]242
[9526]243                // select the object that aim-assistant indicates
244                if(this->closestTarget_)
245                // select the closest object
246                {
247                    if(listIt == this->sortedObjectList_.begin())
248                    {
249                        it->second.selected_ = true;
250                        this->selectedTarget_ = it->first;
251                    }
252                    else if(it->second.selected_)
253                    {
254                        it->second.selected_ = false;
255                    }
256
257                }
258                else if(this->nextTarget_)
259                // select the next object in sortedObjectList
260                {
261                    if(nextHasToBeSelected){
262                        it->second.selected_ = true;
263                        this->selectedTarget_ = it->first;
264                        nextHasToBeSelected = false;
265                    }
266                    else if(it->second.selected_)
267                    {
268                        nextHasToBeSelected = true;
269                        it->second.selected_ = false;
270
271                        // check if there's a next object
272                        listIt++;
273                        if(listIt != this->sortedObjectList_.end())
274                        {
275                            // and if the marker limit and max-distance are not exceeded for it
276                            if (markerCount + 1 >= this->markerLimit_ ||
277                                    (listIt->second > this->detectionLimit_ && detectionLimit_ >= 0))
278                            {
279                                // otherwise select the closest object
280                                this->activeObjectList_.find(this->sortedObjectList_.begin()->first)->second.selected_ = true;
281                                this->selectedTarget_ = it->first;
282                                nextHasToBeSelected = false;
283                            }
284                        }
285                        listIt--;
286                    }
287                }
288
289
[10258]290
291
[9348]292                // Transform to screen coordinates
293                Vector3 pos = camTransform * it->first->getRVWorldPosition();
[9016]294
[9348]295                bool outOfView = true;
296                if (pos.z > 1.0)
297                {
298                    // z > 1.0 means that the object is behind the camera
299                    outOfView = true;
300                    // we have to switch all coordinates (if you don't know why,
301                    // try linear algebra lectures, because I can't explain..)
302                    pos.x = -pos.x;
303                    pos.y = -pos.y;
304                }
305                else
306                    outOfView = pos.x < -1.0 || pos.x > 1.0 || pos.y < -1.0 || pos.y > 1.0;
[9016]307
[9348]308                if (outOfView)
[7163]309                {
[9348]310                    // Object is not in view
311
312                    // Change material only if outOfView changed
313                    if (!it->second.wasOutOfView_)
[7163]314                    {
[10258]315                        it->second.health_->hide();
316                        it->second.healthLevel_->hide();
[9348]317                        it->second.panel_->setMaterialName(TextureGenerator::getMaterialName("arrows.png", it->first->getRadarObjectColour()));
318                        it->second.wasOutOfView_ = true;
[9526]319                        it->second.target_->hide();
[7163]320                    }
[9348]321
322                    //float xDistScale = this->getActualSize().x * 1000.0f * this->navMarkerSize_ / dist;
323                    //float yDistScale = this->getActualSize().y * 1000.0f * this->navMarkerSize_ / dist;
324
325                    // Adjust Arrowsize according to distance
326                    it->second.panel_->setDimensions(getArrowSizeX(dist), getArrowSizeY(dist));
327
328                    // Switch between top, bottom, left and right position of the arrow at the screen border
329                    if (pos.x < pos.y)
330                    {
331                        if (pos.y > -pos.x)
332                        {
333                            // Top
334                            float position = pos.x / pos.y + 1.0f;
335                            it->second.panel_->setPosition((position - it->second.panel_->getWidth()) * 0.5f, 0.0f);
336                            it->second.panel_->setUV(0.5f, 0.0f, 1.0f, 0.5f);
337                            it->second.text_->setLeft((position - textLength) * 0.5f);
338                            it->second.text_->setTop(it->second.panel_->getHeight());
339                        }
340                        else
341                        {
342                            // Left
343                            float position = pos.y / pos.x + 1.0f;
344                            it->second.panel_->setPosition(0.0f, (position - it->second.panel_->getWidth()) * 0.5f);
345                            it->second.panel_->setUV(0.0f, 0.0f, 0.5f, 0.5f);
346                            it->second.text_->setLeft(it->second.panel_->getWidth() + 0.01f);
347                            it->second.text_->setTop((position - it->second.text_->getCharHeight()) * 0.5f);
348                        }
349                    }
[7163]350                    else
351                    {
[9348]352                        if (pos.y < -pos.x)
353                        {
354                            // Bottom
355                            float position = -pos.x / pos.y + 1.0f;
356                            it->second.panel_->setPosition((position - it->second.panel_->getWidth()) * 0.5f, 1.0f - it->second.panel_->getHeight());
357                            it->second.panel_->setUV(0.0f, 0.5f, 0.5f, 1.0f );
358                            it->second.text_->setLeft((position - textLength) * 0.5f);
359                            it->second.text_->setTop(1.0f - it->second.panel_->getHeight() - it->second.text_->getCharHeight());
360                        }
361                        else
362                        {
363                            // Right
364                            float position = -pos.y / pos.x + 1.0f;
365                            it->second.panel_->setPosition(1.0f - it->second.panel_->getWidth(), (position - it->second.panel_->getHeight()) * 0.5f);
366                            it->second.panel_->setUV(0.5f, 0.5f, 1.0f, 1.0f);
367                            it->second.text_->setLeft(1.0f - it->second.panel_->getWidth() - textLength - 0.01f);
368                            it->second.text_->setTop((position - it->second.text_->getCharHeight()) * 0.5f);
369                        }
[7163]370                    }
371                }
[1580]372                else
373                {
[9348]374                    // Object is in view
[7163]375
[10258]376                    //calculate the health of the actual selected radarViewable (relativHealthScale: while (0) is no health left, (1) is the initial health)
[11023]377                    const Pawn* pawnPtr = orxonox_cast<const Pawn*>(it->first->getWorldEntity());
378                    if (pawnPtr)
379                    {
380                        float health = pawnPtr->getHealth();
381                        float initHealth = pawnPtr->getMaxHealth();
382                        float relativHealthScale = health/initHealth;
[10258]383
[11023]384                        //integer values from 0 to 10 (0 is no health and 10 is full health)
385                        int discreteHealthScale = (int)(10*relativHealthScale);
[10258]386
[11023]387                        //calculate the HealthLevel (= OponentLevel or Strength) there are 5 Levels
388                        //Level 1, Level 2,... , Level 5
389                        int HealthLevel = 1;
[10258]390
[11023]391                        if(initHealth < 200)
392                            HealthLevel = 1;
393                        if(200 <= initHealth && initHealth < 500)
394                            HealthLevel = 2;
395                        if(500 <= initHealth && initHealth < 1000)
396                            HealthLevel = 3;
397                        if(1000 <= initHealth && initHealth < 2500)
398                            HealthLevel = 4;
399                        if(2500 <= initHealth)
400                            HealthLevel = 5;
[10258]401
[11023]402                        // Change material only if outOfView changed
403                        if (it->second.wasOutOfView_)
404                        {
405                            //it->second.health_->setMaterialName(TextureGenerator::getMaterialName("bar2_1.png", it->first->getRadarObjectColour()));
406                            it->second.health_->setMaterialName(TextureGenerator::getMaterialName("barSquare.png", it->first->getRadarObjectColour()));
407                            it->second.health_->setDimensions(this->healthMarkerSize_ * this->getActualSize().x , 0.75f*this->healthMarkerSize_ * this->getActualSize().y);
[10258]408
[11023]409                            // because as soon as relative health drops below 10% (0.1) the descrete value is 0 but as long as the
410                            // spaceship is still intact there should be at least one part of the bar left.
411                            if(1<=discreteHealthScale){
412                                it->second.health_->setTiling((float)discreteHealthScale , 1 ,0);
413                                it->second.health_->setDimensions(this->healthMarkerSize_ * this->getActualSize().x *0.1f*discreteHealthScale, 0.75f*this->healthMarkerSize_ * this->getActualSize().y);
414                            }
[10258]415
[11023]416                            //healthLevel
417                            it->second.healthLevel_->setMaterialName(TextureGenerator::getMaterialName("barSquare.png", it->first->getRadarObjectColour()));
418                            it->second.healthLevel_->setDimensions(this->healthLevelMarkerSize_ * this->getActualSize().x , 0.75f*this->healthLevelMarkerSize_ * this->getActualSize().y);
419                            it->second.healthLevel_->setTiling((float)HealthLevel , 1 ,0);
420                            it->second.healthLevel_->setDimensions(this->healthLevelMarkerSize_ * this->getActualSize().x *0.1f*HealthLevel, 0.25f*this->healthLevelMarkerSize_ * this->getActualSize().y);
421                        }
[10258]422
[11023]423                        // sets Position and Dimensions (amount) health
424                        it->second.health_->setUV(0.0f, 0.0f, 1.0f, 1.0f);
425                        it->second.health_->setLeft((pos.x + 0.975f - it->second.panel_->getWidth()) * 0.5f);
426                        it->second.health_->setTop((-pos.y + 1.04f - it->second.panel_->getHeight()) * 0.5f);
[10258]427
428                        // because as soon as relative health drops below 10% (0.1) the descrete value is 0 but as long as the
429                        // spaceship is still intact there should be at least one part of the bar left.
430                        if(1<=discreteHealthScale){
431                            it->second.health_->setTiling((float)discreteHealthScale , 1 ,0);
432                            it->second.health_->setDimensions(this->healthMarkerSize_ * this->getActualSize().x *0.1f*discreteHealthScale, 0.75f*this->healthMarkerSize_ * this->getActualSize().y);
433                        }
434
[11023]435                        //sets Position and Dimensions (level) of healthLevel
436                        it->second.healthLevel_->setMaterialName(TextureGenerator::getMaterialName("barSquare.png", it->first->getRadarObjectColour()));
437                        it->second.healthLevel_->setUV(0.0f, 0.0f, 1.0f, 1.0f);
438                        it->second.healthLevel_->setLeft((pos.x + 0.975f - it->second.panel_->getWidth()) * 0.5f);
439                        it->second.healthLevel_->setTop((-pos.y + 1.125f - it->second.panel_->getHeight()) * 0.5f);
[10258]440
441                        it->second.healthLevel_->setTiling((float)HealthLevel , 1 ,0);
442                        it->second.healthLevel_->setDimensions(this->healthLevelMarkerSize_ * this->getActualSize().x *0.1f*HealthLevel, 0.25f*this->healthLevelMarkerSize_ * this->getActualSize().y);
[11023]443
444                        // Make sure the overlays are shown
445                        it->second.health_->show();
446                        it->second.healthLevel_->show();
[7163]447                    }
[9348]448
[10258]449
[11023]450                    // Change material only if outOfView changed
451                    if (it->second.wasOutOfView_)
452                    {
453                        //it->second.panel_->setMaterialName("Orxonox/NavTDC");
454                        it->second.panel_->setMaterialName(TextureGenerator::getMaterialName("tdc.png", it->first->getRadarObjectColour()));
455                        it->second.panel_->setDimensions(this->navMarkerSize_ * this->getActualSize().x, this->navMarkerSize_ * this->getActualSize().y);
456                        it->second.target_->setDimensions(this->aimMarkerSize_ * this->getActualSize().x, this->aimMarkerSize_ * this->getActualSize().y);
457                        it->second.wasOutOfView_ = false;
[10258]458                    }
459
[9348]460                    // Position marker
461                    it->second.panel_->setUV(0.0f, 0.0f, 1.0f, 1.0f);
462                    it->second.panel_->setLeft((pos.x + 1.0f - it->second.panel_->getWidth()) * 0.5f);
463                    it->second.panel_->setTop((-pos.y + 1.0f - it->second.panel_->getHeight()) * 0.5f);
464
465                    // Position text
466                    it->second.text_->setLeft((pos.x + 1.0f + it->second.panel_->getWidth()) * 0.5f);
467                    it->second.text_->setTop((-pos.y + 1.0f + it->second.panel_->getHeight()) * 0.5f);
[9526]468
469                    // Make sure the overlays are shown
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
[11071]478                            || pawn == nullptr
[9526]479                            /* TODO : improve getTeam in such a way that it works
[11071]480                             * || humanPawn == nullptr
[9526]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
[11071]534        for (const auto& mapEntry : this->activeObjectList_)
[1580]535        {
[11071]536            if (mapEntry.second.health_ != nullptr)
537                mapEntry.second.health_->setDimensions(this->healthMarkerSize_ * xScale, this->healthMarkerSize_ * yScale);
538            if (mapEntry.second.healthLevel_ != nullptr)
539                mapEntry.second.healthLevel_->setDimensions(this->healthLevelMarkerSize_ * xScale, this->healthLevelMarkerSize_ * yScale);
540            if (mapEntry.second.panel_ != nullptr)
541                mapEntry.second.panel_->setDimensions(this->navMarkerSize_ * xScale, this->navMarkerSize_ * yScale);
542            if (mapEntry.second.text_ != nullptr)
543                mapEntry.second.text_->setCharHeight(this->textSize_ * yScale);
544            if (mapEntry.second.target_ != nullptr)
545                mapEntry.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_)
[11071]555        if (object == nullptr)
[9526]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
[11071]643        for (std::list<std::pair<RadarViewable*, unsigned int>>::iterator listIt = this->sortedObjectList_.begin(); listIt != this->sortedObjectList_.end(); ++listIt)
[9348]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();
[11071]673        for (RadarViewable* respawnObject : respawnObjects)
[9348]674        {
[11071]675            if (!respawnObject->isHumanShip_)
676            this->addObject(respawnObject);
[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.