Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/spaceNavigation/src/modules/overlays/hud/HUDAimAssistant.cc @ 9400

Last change on this file since 9400 was 9400, checked in by mottetb, 12 years ago

first checkin

File size: 10.6 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Baptiste Mottet
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29
30
31#include "HUDAimAssistant.h"
32
33#include <OgreCamera.h>
34#include <OgreFontManager.h>
35#include <OgreOverlayManager.h>
36#include <OgreTextAreaOverlayElement.h>
37#include <OgrePanelOverlayElement.h>
38
39#include "util/Math.h"
40#include "util/Convert.h"
41#include "core/CoreIncludes.h"
42#include "core/XMLPort.h"
43#include "CameraManager.h"
44#include "Scene.h"
45#include "Radar.h"
46#include "graphics/Camera.h"
47#include "controllers/HumanController.h"
48#include "worldentities/pawns/Pawn.h"
49#include "worldentities/WorldEntity.h"
50#include "core/ConfigValueIncludes.h"
51#include "tools/TextureGenerator.h"
52
53namespace orxonox
54{
55    CreateFactory ( HUDAimAssistant );
56
57    static bool compareDistance(std::pair<RadarViewable*, unsigned int> a, std::pair<RadarViewable*, unsigned int> b)
58    {
59        return a.second < b.second;
60    }
61
62
63    HUDAimAssistant::HUDAimAssistant(BaseObject* creator) : OrxonoxOverlay(creator)
64    {
65        RegisterObject(HUDAimAssistant);
66        this->setConfigValues();
67
68        // Set default values
69        this->setPointerSize(0.03f);
70        this->setDetectionLimit(10000.0f);
71    }
72
73    HUDAimAssistant::~HUDAimAssistant()
74    {
75        if (this->isInitialized())
76        {
77            for (std::map<RadarViewable*, ObjectInfo>::iterator it = this->activeObjectList_.begin(); it != this->activeObjectList_.end();)
78                removeObject((it++)->first);
79        }
80        this->sortedObjectList_.clear();
81    }
82
83    void HUDAimAssistant::setConfigValues()
84    {
85        SetConfigValue(markerLimit_, 3);
86    }
87
88    void HUDAimAssistant::XMLPort(Element& xmlelement, XMLPort::Mode mode)
89    {
90        SUPER(HUDAimAssistant, XMLPort, xmlelement, mode);
91
92        XMLPortParam(HUDAimAssistant, "pointerSize",    setPointerSize,    getPointerSize,  xmlelement, mode);
93        XMLPortParam(HUDAimAssistant, "detectionLimit", setDetectionLimit, getDetectionLimit, xmlelement, mode);
94    }
95
96    void HUDAimAssistant::tick(float dt)
97    {
98        SUPER(HUDAimAssistant, tick, dt);
99
100        Camera* cam = CameraManager::getInstance().getActiveCamera();
101        if (cam == NULL)
102            return;
103        const Matrix4& camTransform = cam->getOgreCamera()->getProjectionMatrix() * cam->getOgreCamera()->getViewMatrix();
104
105
106        for (std::list<std::pair<RadarViewable*, unsigned int> >::iterator listIt = this->sortedObjectList_.begin(); listIt != this->sortedObjectList_.end(); ++listIt)
107            listIt->second = (int)((listIt->first->getRVWorldPosition() - HumanController::getLocalControllerSingleton()->getControllableEntity()->getWorldPosition()).length() + 0.5f);
108
109        this->sortedObjectList_.sort(compareDistance);
110
111        unsigned int markerCount = 0;
112        bool closeEnough = false; // only display objects that are close enough to be relevant for the player
113
114        for (std::list<std::pair<RadarViewable*, unsigned int> >::iterator listIt = this->sortedObjectList_.begin(); listIt != this->sortedObjectList_.end(); ++markerCount, ++listIt)
115        {
116            std::map<RadarViewable*, ObjectInfo>::iterator it = this->activeObjectList_.find(listIt->first);
117            closeEnough = listIt->second < this->detectionLimit_;
118            // display radarviewables on HUD if the marker limit and max-distance is not exceeded
119            if (markerCount < this->markerLimit_ && (closeEnough ||  this->detectionLimit_ < 0))
120            {
121                // Get Distance to HumanController and save it in the TextAreaOverlayElement.
122                int dist = listIt->second;
123                float textLength = 0.0f;
124
125               // Transform to screen coordinates
126                Vector3 pos = camTransform * it->first->getRVWorldPosition();
127
128                bool outOfView = true;
129                if (pos.z > 1.0)
130                {
131                    // z > 1.0 means that the object is behind the camera
132                    outOfView = true;
133                    // we have to switch all coordinates (if you don't know why,
134                    // try linear algebra lectures, because I can't explain..)
135                    pos.x = -pos.x;
136                    pos.y = -pos.y;
137                }
138                else
139                    outOfView = pos.x < -1.0 || pos.x > 1.0 || pos.y < -1.0 || pos.y > 1.0;
140
141                if (outOfView)
142                {
143                    // Object is not in view
144
145                    // Hide if outOfView changed
146                    if (!it->second.wasOutOfView_)
147                    {
148                        it->second.panel_->hide();
149                        it->second.wasOutOfView_ = true;
150                    }
151
152                }
153                else
154                {
155                    // Object is in view
156
157                    // Change material only if outOfView changed
158                    if (it->second.wasOutOfView_)
159                    {
160                        //it->second.panel_->setMaterialName("Orxonox/NavTDC");
161                        it->second.panel_->setMaterialName(TextureGenerator::getMaterialName("aimassistant.png", it->first->getRadarObjectColour()));
162                        it->second.panel_->setDimensions(this->pointerSize_ * this->getActualSize().x, this->pointerSize_ * this->getActualSize().y);
163                        it->second.wasOutOfView_ = false;
164                    }
165
166                    // Position marker
167                    it->second.panel_->setUV(0.0f, 0.0f, 1.0f, 1.0f);
168                    it->second.panel_->setLeft((pos.x + 1.0f - it->second.panel_->getWidth()) * 0.5f);
169                    it->second.panel_->setTop((-pos.y + 1.0f - it->second.panel_->getHeight()) * 0.5f);
170                }
171
172                // Make sure the overlays are shown
173                it->second.panel_->show();
174            }
175            else // do not display on HUD
176            {
177                it->second.panel_->hide();
178            }
179        }
180    }
181
182    /** Overridden method of OrxonoxOverlay.
183    @details
184        Usually the entire overlay scales with scale().
185        Here we obviously have to adjust this.
186    */
187    void HUDAimAssistant::sizeChanged()
188    {
189        // Use size to compensate for aspect ratio if enabled.
190        float xScale = this->getActualSize().x;
191        float yScale = this->getActualSize().y;
192
193        for (std::map<RadarViewable*, ObjectInfo>::iterator it = this->activeObjectList_.begin(); it != this->activeObjectList_.end(); ++it)
194        {
195            if (it->second.panel_ != NULL)
196                it->second.panel_->setDimensions(this->pointerSize_ * xScale, this->pointerSize_ * yScale);
197        }
198    }
199
200    void HUDAimAssistant::addObject(RadarViewable* object)
201    {
202        if (showObject(object) == false)
203            return;
204
205        if (this->activeObjectList_.size() >= this->markerLimit_)
206            if (object == NULL)
207                return;
208
209        // Object hasn't been added yet (we know that)
210        assert(this->activeObjectList_.find(object) == this->activeObjectList_.end());
211
212        // Scales used for dimensions and text size
213        float xScale = this->getActualSize().x;
214        float yScale = this->getActualSize().y;
215
216        // Create everything needed to display the object on the radar and add it to the map
217
218        // Create arrow/marker
219        Ogre::PanelOverlayElement* panel = static_cast<Ogre::PanelOverlayElement*>( Ogre::OverlayManager::getSingleton()
220                                           .createOverlayElement("Panel", "HUDAimAssistant_pointer_" + getUniqueNumberString()));
221        //panel->setMaterialName("Orxonox/NavTDC");
222        panel->setMaterialName(TextureGenerator::getMaterialName("tdc.png", object->getRadarObjectColour()));
223        panel->setDimensions(this->pointerSize_ * xScale, this->pointerSize_ * yScale);
224        //panel->setColour(object->getRadarObjectColour());
225
226
227        ObjectInfo tempStruct = {panel, false /*, TODO: initialize wasOutOfView_ */};
228        this->activeObjectList_[object] = tempStruct;
229
230        this->background_->addChild(panel);
231
232        this->sortedObjectList_.push_front(std::make_pair(object, (unsigned int)0));
233    }
234
235    void HUDAimAssistant::removeObject(RadarViewable* viewable)
236    {
237        std::map<RadarViewable*, ObjectInfo>::iterator it = this->activeObjectList_.find(viewable);
238
239        if (this->activeObjectList_.find(viewable) != this->activeObjectList_.end())
240        {
241            // Detach overlays
242            this->background_->removeChild(it->second.panel_->getName());
243            // Properly destroy the overlay elements (do not use delete!)
244            Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.panel_);
245            // Remove from the list
246            this->activeObjectList_.erase(viewable);
247        }
248
249        for (std::list<std::pair<RadarViewable*, unsigned int> >::iterator listIt = this->sortedObjectList_.begin(); listIt != this->sortedObjectList_.end(); ++listIt)
250        {
251            if ((listIt->first) == viewable)
252            {
253                this->sortedObjectList_.erase(listIt);
254                break;
255            }
256        }
257    }
258
259    void HUDAimAssistant::objectChanged(RadarViewable* viewable)
260    {
261        // TODO: niceification neccessary ;)
262        removeObject(viewable);
263        addObject(viewable);
264    }
265
266    bool HUDAimAssistant::showObject(RadarViewable* rv)
267    {
268        if (rv == orxonox_cast<RadarViewable*>(this->getOwner()))
269            return false;
270        assert(rv->getWorldEntity());
271        if (rv->getWorldEntity()->isVisible() == false || rv->getRadarVisibility() == false)
272            return false;
273        return true;
274    }
275
276    void HUDAimAssistant::changedOwner()
277    {
278        const std::set<RadarViewable*>& respawnObjects = this->getOwner()->getScene()->getRadar()->getRadarObjects();
279        for (std::set<RadarViewable*>::const_iterator it = respawnObjects.begin(); it != respawnObjects.end(); ++it)
280        {
281            if (!(*it)->isHumanShip_)
282                this->addObject(*it);
283        }
284    }
285}
Note: See TracBrowser for help on using the repository browser.