Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentationHS15/src/orxonox/overlays/OrxonoxOverlay.cc @ 11056

Last change on this file since 11056 was 10961, checked in by maxima, 10 years ago

Merged presentation and fabiens branch. Had to modify hoverHUD and invaderHUD, because the text of the healthbar wasn't correctly displayed and the weapon settings of the hovership.

  • Property svn:eol-style set to native
File size: 15.8 KB
RevLine 
[1588]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 *      Reto Grieder
24 *   Co-authors:
25 *      ...
26 *
27 */
28
[1622]29/**
30@file
31@brief Definition of the OrxonoxOverlay class.
32*/
33
[1601]34#include "OrxonoxOverlay.h"
[1588]35
[1615]36#include <cmath>
[1622]37#include <OgreOverlay.h>
[1588]38#include <OgreOverlayManager.h>
[1614]39#include <OgrePanelOverlayElement.h>
[2896]40#include <OgreRenderWindow.h>
[6417]41#include <OgreMaterialManager.h>
42#include <OgreTechnique.h>
43#include <OgrePass.h>
[2896]44
[1588]45#include "util/Convert.h"
[2171]46#include "util/Exception.h"
[2896]47#include "core/GameMode.h"
[1588]48#include "core/CoreIncludes.h"
[1616]49#include "core/XMLPort.h"
[10624]50#include "core/command/ConsoleCommandIncludes.h"
[1588]51
[5980]52#include "OverlayGroup.h"
53
[1588]54namespace orxonox
55{
[1615]56    unsigned int OrxonoxOverlay::hudOverlayCounter_s = 0;
57    std::map<std::string, OrxonoxOverlay*> OrxonoxOverlay::overlays_s;
[1588]58
[7284]59    SetConsoleCommand("OrxonoxOverlay", "scaleOverlay",     &OrxonoxOverlay::scaleOverlay);
60    SetConsoleCommand("OrxonoxOverlay", "scrollOverlay",    &OrxonoxOverlay::scrollOverlay);
61    SetConsoleCommand("OrxonoxOverlay", "toggleVisibility", &OrxonoxOverlay::toggleVisibility);
[8309]62    SetConsoleCommand("OrxonoxOverlay", "show",     &OrxonoxOverlay::showOverlay);
[7284]63    SetConsoleCommand("OrxonoxOverlay", "rotateOverlay",    &OrxonoxOverlay::rotateOverlay);
[1588]64
[9667]65    RegisterClass(OrxonoxOverlay);
66
67    OrxonoxOverlay::OrxonoxOverlay(Context* context)
68        : BaseObject(context)
[1615]69    {
70        RegisterObject(OrxonoxOverlay);
[2087]71
[2662]72        this->owner_ = 0;
73        this->group_ = 0;
74
[2896]75        if (!GameMode::showsGraphics())
[2171]76            ThrowException(NoGraphics, "Can't create OrxonoxOverlay, graphics engine not initialized");
77
[2087]78        // create the Ogre::Overlay
79        overlay_ = Ogre::OverlayManager::getSingleton().create("OrxonoxOverlay_overlay_"
[3280]80            + multi_cast<std::string>(hudOverlayCounter_s++));
[2087]81
82        // create background panel (can be used to show any picture)
83        this->background_ = static_cast<Ogre::PanelOverlayElement*>(
84            Ogre::OverlayManager::getSingleton().createOverlayElement("Panel",
[3280]85            "OrxonoxOverlay_background_" + multi_cast<std::string>(hudOverlayCounter_s++)));
[2087]86        this->overlay_->add2D(this->background_);
87
[2896]88        // Get aspect ratio from the render window. Later on, we get informed automatically
[3327]89        this->windowAspectRatio_ = static_cast<float>(this->getWindowWidth()) / this->getWindowHeight();
[2087]90
[6417]91        this->size_ = Vector2(1.0f, 1.0f);
92        this->pickPoint_= Vector2(0.0f, 0.0f);
93        this->position_ = Vector2(0.0f, 0.0f);
94        this->angle_ = Degree(0.0);
95        this->bCorrectAspect_ = false;
96        this->rotState_ = Horizontal;
97        this->angleChanged(); // updates all other values as well
[2087]98
99        setBackgroundMaterial("");
[1615]100    }
[1614]101
[1622]102    /**
103    @brief
104        Make sure everything gets removed/destroyed.
105    @remark
106        We assume that the Ogre::OverlayManager exists (there is an assert in Ogre for that!)
107    */
[1615]108    OrxonoxOverlay::~OrxonoxOverlay()
109    {
[2087]110        if (this->isInitialized())
111        {
112            // erase ourself from the map with all overlays
113            std::map<std::string, OrxonoxOverlay*>::iterator it = overlays_s.find(this->getName());
114            if (it != overlays_s.end())
115                overlays_s.erase(it);
[1622]116
117            Ogre::OverlayManager::getSingleton().destroyOverlayElement(this->background_);
118            Ogre::OverlayManager::getSingleton().destroy(this->overlay_);
[2087]119        }
[1615]120    }
121
[1622]122    /**
123    @brief
124        Loads the OrxonoxOverlay.
[1747]125
[1622]126        This has to be called before usage, otherwise strange behaviour is
127        guaranteed! (there should be no segfaults however).
128    @copydoc
129        BaseObject::XMLPort()
130    */
[7401]131    void OrxonoxOverlay::XMLPort(Element& xmlelement, XMLPort::Mode mode)
[1590]132    {
[7401]133        SUPER(OrxonoxOverlay, XMLPort, xmlelement, mode);
[1588]134
[7401]135        XMLPortParam(OrxonoxOverlay, "size",      setSize,      getSize,      xmlelement, mode);
136        XMLPortParam(OrxonoxOverlay, "pickpoint", setPickPoint, getPickPoint, xmlelement, mode);
137        XMLPortParam(OrxonoxOverlay, "position",  setPosition,  getPosition,  xmlelement, mode);
138        XMLPortParam(OrxonoxOverlay, "rotation",  setRotation,  getRotation,  xmlelement, mode);
139        XMLPortParam(OrxonoxOverlay, "correctaspect", setAspectCorrection,   getAspectCorrection,   xmlelement, mode);
140        XMLPortParam(OrxonoxOverlay, "background",    setBackgroundMaterial, getBackgroundMaterial, xmlelement, mode);
[8706]141        XMLPortParam(OrxonoxOverlay, "backgroundtex", setBackgroundTexture,  getBackgroundTexture,  xmlelement, mode);
[2087]142    }
[1614]143
[2087]144    void OrxonoxOverlay::changedName()
145    {
[2662]146        SUPER(OrxonoxOverlay, changedName);
147
[2087]148        OrxonoxOverlay::overlays_s.erase(this->getOldName());
[1590]149
[2087]150        if (OrxonoxOverlay::overlays_s.find(this->getName()) != OrxonoxOverlay::overlays_s.end())
[8858]151            orxout(internal_warning) << "Overlay names should be unique or you cannnot access them via console. Name: \"" << this->getName() << '"' << endl;
[1588]152
[2087]153        OrxonoxOverlay::overlays_s[this->getName()] = this;
[1590]154    }
[1588]155
[1622]156    //! Only sets the background material name if not ""
[1615]157    void OrxonoxOverlay::setBackgroundMaterial(const std::string& material)
158    {
[6417]159        if (this->background_ && !material.empty())
[1615]160            this->background_->setMaterialName(material);
161    }
[1588]162
[1622]163    //! Returns the the material name of the background
[1615]164    const std::string& OrxonoxOverlay::getBackgroundMaterial() const
165    {
166        if (this->background_)
167            return this->background_->getMaterialName();
168        else
[2087]169            return BLANKSTRING;
[1615]170    }
[1614]171
[8706]172    //! Sets the background texture name and creates a new material if necessary
173    void OrxonoxOverlay::setBackgroundTexture(const std::string& texture)
174    {
175        if (this->background_ && this->background_->getMaterial().isNull() && !texture.empty())
176        {
177            // create new material
178            const std::string& materialname = "generated_material" + getUniqueNumberString();
179            Ogre::MaterialPtr material = static_cast<Ogre::MaterialPtr>(Ogre::MaterialManager::getSingleton().create(materialname, "General"));
180            material->getTechnique(0)->getPass(0)->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
181            Ogre::TextureUnitState* textureUnitState_ = material->getTechnique(0)->getPass(0)->createTextureUnitState();
182            textureUnitState_->setTextureName(texture);
183            textureUnitState_->setNumMipmaps(0);
184            this->background_->setMaterialName(materialname);
185        }
186    }
187
188    //! Returns the the texture name of the background
189    const std::string& OrxonoxOverlay::getBackgroundTexture() const
190    {
191        if (this->background_)
192        {
193            Ogre::TextureUnitState* tempTx = this->background_->getMaterial()->getTechnique(0)->getPass(0)->getTextureUnitState(0);
194            return tempTx->getTextureName();
195        }
196        else
197            return BLANKSTRING;
198    }
199
[1622]200    //! Called by BaseObject when visibility has changed.
[1615]201    void OrxonoxOverlay::changedVisibility()
[1595]202    {
[5980]203        SUPER( OrxonoxOverlay, changedVisibility );
[6417]204
[1622]205        if (!this->overlay_)
206            return;
207
[5980]208        // only set to visible if corresponding OverlayGroup is also visible
209        if (this->isVisible() && (!this->getOverlayGroup() || this->getOverlayGroup()->isVisible()) )
[1622]210            this->overlay_->show();
211        else
212            this->overlay_->hide();
[1595]213    }
[1588]214
[1622]215    /**
216    @brief
[2896]217        Called by the GraphicsManager whenever the window size changes.
[1622]218        Calculates the aspect ratio only.
219    */
[2896]220    void OrxonoxOverlay::windowResized(unsigned int newWidth, unsigned int newHeight)
[1615]221    {
[3301]222        this->windowAspectRatio_ = static_cast<float>(newWidth) / newHeight;
[1622]223        this->sizeCorrectionChanged();
[1615]224    }
[1590]225
[1622]226    /**
227    @brief
228        Called whenever the rotation angle has changed.
229    */
230    void OrxonoxOverlay::angleChanged()
[1595]231    {
[1622]232        if (!this->overlay_)
233            return;
234
235        this->overlay_->setRotate(this->angle_);
[1615]236        this->sizeCorrectionChanged();
[1595]237    }
[1615]238
[1622]239    /**
240    @brief
241        Called whenever the aspect ratio or the angle has changed.
242        The method calculates a correction factor for the size to compensate
243        for aspect distortion if desired.
244    @remarks
245        This only works when the angle is about 0 or 90 degrees.
246    */
[1615]247    void OrxonoxOverlay::sizeCorrectionChanged()
[1595]248    {
[1615]249        if (this->bCorrectAspect_)
250        {
251            float angle = this->angle_.valueDegrees();
[1618]252            if (angle < 0.0)
253                angle = -angle;
[3301]254            angle -= 180.0f * static_cast<int>(angle / 180.0);
[1618]255
[1622]256            // take the reverse if angle is about 90 degrees
[1615]257            float tempAspect;
[3196]258            if (angle > 89.0f && angle < 91.0f)
[1632]259            {
[6502]260                tempAspect = 1.0f / this->windowAspectRatio_;
[1632]261                rotState_ = Vertical;
262            }
[1618]263            else if (angle > 179 || angle < 1)
[1632]264            {
[1615]265                tempAspect = this->windowAspectRatio_;
[1632]266                rotState_ = Horizontal;
267            }
[1615]268            else
[1632]269            {
[3196]270                tempAspect = 1.0f;
[1632]271                rotState_ = Inbetween;
272            }
[1615]273
274            // note: this is only an approximation that is mostly valid when the
275            // magnitude of the width is about the magnitude of the height.
276            // Correctly we would have to take the square root of width*height
[3196]277            this->sizeCorrection_.x = 2.0f / (tempAspect + 1.0f);
[1615]278            this->sizeCorrection_.y = tempAspect * this->sizeCorrection_.x;
279        }
280        else
281        {
282            this->sizeCorrection_ = Vector2::UNIT_SCALE;
283        }
[1622]284
[1615]285        this->sizeChanged();
[1595]286    }
287
[1615]288    /**
[1622]289    @brief
290        Sets the overlay size using the actual corrected size.
[1615]291    */
292    void OrxonoxOverlay::sizeChanged()
293    {
[1622]294        if (!this->overlay_)
295            return;
296
[1615]297        this->overlay_->setScale(size_.x * sizeCorrection_.x, size_.y * sizeCorrection_.y);
298        positionChanged();
299    }
[1595]300
[1615]301    /**
[1622]302    @brief
303        Determines the position of the overlay.
304        This works also well when a rotation angle is applied. The overlay always
305        gets aligned correctly as well as possible.
[1615]306    */
[1622]307    void OrxonoxOverlay::positionChanged()
[1615]308    {
[1622]309        if (!this->overlay_)
310            return;
[1595]311
[1622]312        // transform the angle to a range of 0 - pi/2 first.
[1617]313        float angle = this->angle_.valueRadians();
314        if (angle < 0.0)
315            angle = -angle;
[7184]316        angle -= math::pi * static_cast<int>(angle / (math::pi));
[8351]317        if (angle > math::pi_2)
[7184]318            angle = math::pi - angle;
[1747]319
[1622]320        // do some mathematical fiddling for a bounding box
[1615]321        Vector2 actualSize = size_ * sizeCorrection_;
322        float radius = actualSize.length();
323        float phi = atan(actualSize.y / actualSize.x);
324        Vector2 boundingBox(radius * cos(angle - phi), radius * sin(angle + phi));
[1622]325
326        // calculate the scrolling offset
327        Vector2 scroll = (position_ - 0.5 - boundingBox * (pickPoint_ - 0.5)) * 2.0;
[1615]328        this->overlay_->setScroll(scroll.x, -scroll.y);
329    }
[1598]330
[1615]331
[1622]332    //########### Console commands ############
333
334    /**
335    @brief
336        Scales an overlay by its name.
337    @param name
338        The name of the overlay defined BaseObject::setName() (usually done with the "name"
[1623]339        attribute in the xml file).
[7401]340    @param scale
341        The scaling factor
[1622]342    */
[1615]343    /*static*/ void OrxonoxOverlay::scaleOverlay(const std::string& name, float scale)
344    {
345        std::map<std::string, OrxonoxOverlay*>::const_iterator it = overlays_s.find(name);
346        if (it != overlays_s.end())
[6417]347            it->second->scale(Vector2(scale, scale));
[1615]348    }
349
[1622]350    /**
351    @brief
[2993]352        Toggles the visibility of an Overlay by it's name.
353    @param name
354        The name of the overlay defined BaseObject::setName() (usually done with the "name"
355        attribute in the xml file).
356    */
357    /*static*/ void OrxonoxOverlay::toggleVisibility(const std::string& name)
358    {
359        std::map<std::string, OrxonoxOverlay*>::const_iterator it = overlays_s.find(name);
360        if (it != overlays_s.end())
361        {
[6417]362            OrxonoxOverlay* overlay= it->second;
[2993]363            if(overlay->isVisible())
[6711]364            {
[2993]365                overlay->hide();
[8858]366                orxout(verbose, context::misc::overlays) << "HIDE " << name << endl;
[6711]367            }
[2993]368            else
[6711]369            {
[2993]370                overlay->show();
[8858]371                orxout(verbose, context::misc::overlays) << "SHOW " << name << endl;
[6711]372            }
[2993]373        }
374    }
[8309]375   
376    /**
377    @brief
378        Shows Overlay by it's name.
379    @param name
380        The name of the overlay defined BaseObject::setName() (usually done with the "name"
381        attribute in the xml file).
382    */
383    /*static*/ void OrxonoxOverlay::showOverlay(const std::string& name)
384    {
385        std::map<std::string, OrxonoxOverlay*>::const_iterator it = overlays_s.find(name);
386        if (it != overlays_s.end())
387        {
388            OrxonoxOverlay* overlay= it->second;
389            if(overlay->isVisible())
390                overlay->changedVisibility();
391            else
392                overlay->show();
393        }
394    }
[2993]395
396    /**
397    @brief
[1622]398        Scrolls an overlay by its name.
399    @param name
400        The name of the overlay defined BaseObject::setName() (usually done with the "name"
[1623]401        attribute in the xml file).
[7401]402    @param scroll
403        The relative translation of the overlay
[1622]404    */
[1615]405    /*static*/ void OrxonoxOverlay::scrollOverlay(const std::string& name, const Vector2& scroll)
406    {
407        std::map<std::string, OrxonoxOverlay*>::const_iterator it = overlays_s.find(name);
408        if (it != overlays_s.end())
[6417]409            it->second->scroll(scroll);
[1615]410    }
411
[1622]412    /**
413    @brief
414        Rotates an overlay by its name.
415    @param name
416        The name of the overlay defined BaseObject::setName() (usually done with the "name"
[1623]417        attribute in the xml file).
[7401]418    @param angle
419        The rotation angle in degree
[1622]420    */
[1615]421    /*static*/ void OrxonoxOverlay::rotateOverlay(const std::string& name, const Degree& angle)
422    {
423        std::map<std::string, OrxonoxOverlay*>::const_iterator it = overlays_s.find(name);
424        if (it != overlays_s.end())
[6417]425            it->second->rotate(angle);
[1615]426    }
[6057]427
428    void OrxonoxOverlay::setOverlayGroup(OverlayGroup* group)
429    {
430        if (group != this->group_)
431        {
432            if (this->group_)
433                this->group_->removeElement(this);
434            this->group_ = group;
435            this->changedOverlayGroup();
436        }
437    }
[6417]438
[8706]439    void OrxonoxOverlay::setBackgroundAlpha(float alpha)
440    {
[6417]441        Ogre::MaterialPtr ptr = this->background_->getMaterial();
442        Ogre::TextureUnitState* tempTx = ptr->getTechnique(0)->getPass(0)->getTextureUnitState(0);
443        tempTx->setAlphaOperation(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, alpha);
444    }
[8706]445
446    void OrxonoxOverlay::setBackgroundColour(ColourValue colour)
447    {
448        Ogre::MaterialPtr ptr = this->background_->getMaterial();
449        Ogre::TextureUnitState* tempTx = ptr->getTechnique(0)->getPass(0)->getTextureUnitState(0);
450        tempTx->setColourOperationEx(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, colour);
451    }
[10961]452
453    void OrxonoxOverlay::setZOrder(unsigned short order)
454    {
455        if (this->overlay_)
456        {
457            this->overlay_->setZOrder(order);
458        }
459    }
[1588]460}
Note: See TracBrowser for help on using the repository browser.