Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/consolecommands3/src/orxonox/overlays/OrxonoxOverlay.cc @ 7674

Last change on this file since 7674 was 7236, checked in by landauf, 14 years ago

replaced the temporary names of all ConsoleCommand related classes and functions by their real names

  • Property svn:eol-style set to native
File size: 12.9 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"
[7204]50#include "core/command/ConsoleCommand.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
[7236]59    SetConsoleCommand("OrxonoxOverlay", "scaleOverlay",     &OrxonoxOverlay::scaleOverlay);
60    SetConsoleCommand("OrxonoxOverlay", "scrollOverlay",    &OrxonoxOverlay::scrollOverlay);
61    SetConsoleCommand("OrxonoxOverlay", "toggleVisibility", &OrxonoxOverlay::toggleVisibility);
62    SetConsoleCommand("OrxonoxOverlay", "rotateOverlay",    &OrxonoxOverlay::rotateOverlay);
[1588]63
[2087]64    OrxonoxOverlay::OrxonoxOverlay(BaseObject* creator)
65        : BaseObject(creator)
[1615]66    {
67        RegisterObject(OrxonoxOverlay);
[2087]68
[2662]69        this->owner_ = 0;
70        this->group_ = 0;
71
[2896]72        if (!GameMode::showsGraphics())
[2171]73            ThrowException(NoGraphics, "Can't create OrxonoxOverlay, graphics engine not initialized");
74
[2087]75        // create the Ogre::Overlay
76        overlay_ = Ogre::OverlayManager::getSingleton().create("OrxonoxOverlay_overlay_"
[3280]77            + multi_cast<std::string>(hudOverlayCounter_s++));
[2087]78
79        // create background panel (can be used to show any picture)
80        this->background_ = static_cast<Ogre::PanelOverlayElement*>(
81            Ogre::OverlayManager::getSingleton().createOverlayElement("Panel",
[3280]82            "OrxonoxOverlay_background_" + multi_cast<std::string>(hudOverlayCounter_s++)));
[2087]83        this->overlay_->add2D(this->background_);
84
[2896]85        // Get aspect ratio from the render window. Later on, we get informed automatically
[3327]86        this->windowAspectRatio_ = static_cast<float>(this->getWindowWidth()) / this->getWindowHeight();
[2087]87
[6417]88        this->size_ = Vector2(1.0f, 1.0f);
89        this->pickPoint_= Vector2(0.0f, 0.0f);
90        this->position_ = Vector2(0.0f, 0.0f);
91        this->angle_ = Degree(0.0);
92        this->bCorrectAspect_ = false;
93        this->rotState_ = Horizontal;
94        this->angleChanged(); // updates all other values as well
[2087]95
96        setBackgroundMaterial("");
[1615]97    }
[1614]98
[1622]99    /**
100    @brief
101        Make sure everything gets removed/destroyed.
102    @remark
103        We assume that the Ogre::OverlayManager exists (there is an assert in Ogre for that!)
104    */
[1615]105    OrxonoxOverlay::~OrxonoxOverlay()
106    {
[2087]107        if (this->isInitialized())
108        {
109            // erase ourself from the map with all overlays
110            std::map<std::string, OrxonoxOverlay*>::iterator it = overlays_s.find(this->getName());
111            if (it != overlays_s.end())
112                overlays_s.erase(it);
[1622]113
114            Ogre::OverlayManager::getSingleton().destroyOverlayElement(this->background_);
115            Ogre::OverlayManager::getSingleton().destroy(this->overlay_);
[2087]116        }
[1615]117    }
118
[1622]119    /**
120    @brief
121        Loads the OrxonoxOverlay.
[1747]122
[1622]123        This has to be called before usage, otherwise strange behaviour is
124        guaranteed! (there should be no segfaults however).
125    @copydoc
126        BaseObject::XMLPort()
127    */
[1615]128    void OrxonoxOverlay::XMLPort(Element& xmlElement, XMLPort::Mode mode)
[1590]129    {
[1747]130        SUPER(OrxonoxOverlay, XMLPort, xmlElement, mode);
[1588]131
[2087]132        XMLPortParam(OrxonoxOverlay, "size",      setSize,      getSize,      xmlElement, mode);
[2662]133        XMLPortParam(OrxonoxOverlay, "pickpoint", setPickPoint, getPickPoint, xmlElement, mode);
[2087]134        XMLPortParam(OrxonoxOverlay, "position",  setPosition,  getPosition,  xmlElement, mode);
135        XMLPortParam(OrxonoxOverlay, "rotation",  setRotation,  getRotation,  xmlElement, mode);
[2662]136        XMLPortParam(OrxonoxOverlay, "correctaspect", setAspectCorrection,   getAspectCorrection,   xmlElement, mode);
[2087]137        XMLPortParam(OrxonoxOverlay, "background",    setBackgroundMaterial, getBackgroundMaterial, xmlElement, mode);
138    }
[1614]139
[2087]140    void OrxonoxOverlay::changedName()
141    {
[2662]142        SUPER(OrxonoxOverlay, changedName);
143
[2087]144        OrxonoxOverlay::overlays_s.erase(this->getOldName());
[1590]145
[2087]146        if (OrxonoxOverlay::overlays_s.find(this->getName()) != OrxonoxOverlay::overlays_s.end())
[6417]147            COUT(1) << "Overlay names should be unique or you cannnot access them via console. Name: \"" << this->getName() << '"' << std::endl;
[1588]148
[2087]149        OrxonoxOverlay::overlays_s[this->getName()] = this;
[1590]150    }
[1588]151
[1622]152    //! Only sets the background material name if not ""
[1615]153    void OrxonoxOverlay::setBackgroundMaterial(const std::string& material)
154    {
[6417]155        if (this->background_ && !material.empty())
[1615]156            this->background_->setMaterialName(material);
157    }
[1588]158
[1622]159    //! Returns the the material name of the background
[1615]160    const std::string& OrxonoxOverlay::getBackgroundMaterial() const
161    {
162        if (this->background_)
163            return this->background_->getMaterialName();
164        else
[2087]165            return BLANKSTRING;
[1615]166    }
[1614]167
[1622]168    //! Called by BaseObject when visibility has changed.
[1615]169    void OrxonoxOverlay::changedVisibility()
[1595]170    {
[5980]171        SUPER( OrxonoxOverlay, changedVisibility );
[6417]172
[1622]173        if (!this->overlay_)
174            return;
175
[5980]176        // only set to visible if corresponding OverlayGroup is also visible
177        if (this->isVisible() && (!this->getOverlayGroup() || this->getOverlayGroup()->isVisible()) )
[1622]178            this->overlay_->show();
179        else
180            this->overlay_->hide();
[1595]181    }
[1588]182
[1622]183    /**
184    @brief
[2896]185        Called by the GraphicsManager whenever the window size changes.
[1622]186        Calculates the aspect ratio only.
187    */
[2896]188    void OrxonoxOverlay::windowResized(unsigned int newWidth, unsigned int newHeight)
[1615]189    {
[3301]190        this->windowAspectRatio_ = static_cast<float>(newWidth) / newHeight;
[1622]191        this->sizeCorrectionChanged();
[1615]192    }
[1590]193
[1622]194    /**
195    @brief
196        Called whenever the rotation angle has changed.
197    */
198    void OrxonoxOverlay::angleChanged()
[1595]199    {
[1622]200        if (!this->overlay_)
201            return;
202
203        this->overlay_->setRotate(this->angle_);
[1615]204        this->sizeCorrectionChanged();
[1595]205    }
[1615]206
[1622]207    /**
208    @brief
209        Called whenever the aspect ratio or the angle has changed.
210        The method calculates a correction factor for the size to compensate
211        for aspect distortion if desired.
212    @remarks
213        This only works when the angle is about 0 or 90 degrees.
214    */
[1615]215    void OrxonoxOverlay::sizeCorrectionChanged()
[1595]216    {
[1615]217        if (this->bCorrectAspect_)
218        {
219            float angle = this->angle_.valueDegrees();
[1618]220            if (angle < 0.0)
221                angle = -angle;
[3301]222            angle -= 180.0f * static_cast<int>(angle / 180.0);
[1618]223
[1622]224            // take the reverse if angle is about 90 degrees
[1615]225            float tempAspect;
[3196]226            if (angle > 89.0f && angle < 91.0f)
[1632]227            {
[6502]228                tempAspect = 1.0f / this->windowAspectRatio_;
[1632]229                rotState_ = Vertical;
230            }
[1618]231            else if (angle > 179 || angle < 1)
[1632]232            {
[1615]233                tempAspect = this->windowAspectRatio_;
[1632]234                rotState_ = Horizontal;
235            }
[1615]236            else
[1632]237            {
[3196]238                tempAspect = 1.0f;
[1632]239                rotState_ = Inbetween;
240            }
[1615]241
242            // note: this is only an approximation that is mostly valid when the
243            // magnitude of the width is about the magnitude of the height.
244            // Correctly we would have to take the square root of width*height
[3196]245            this->sizeCorrection_.x = 2.0f / (tempAspect + 1.0f);
[1615]246            this->sizeCorrection_.y = tempAspect * this->sizeCorrection_.x;
247        }
248        else
249        {
250            this->sizeCorrection_ = Vector2::UNIT_SCALE;
251        }
[1622]252
[1615]253        this->sizeChanged();
[1595]254    }
255
[1615]256    /**
[1622]257    @brief
258        Sets the overlay size using the actual corrected size.
[1615]259    */
260    void OrxonoxOverlay::sizeChanged()
261    {
[1622]262        if (!this->overlay_)
263            return;
264
[1615]265        this->overlay_->setScale(size_.x * sizeCorrection_.x, size_.y * sizeCorrection_.y);
266        positionChanged();
267    }
[1595]268
[1615]269    /**
[1622]270    @brief
271        Determines the position of the overlay.
272        This works also well when a rotation angle is applied. The overlay always
273        gets aligned correctly as well as possible.
[1615]274    */
[1622]275    void OrxonoxOverlay::positionChanged()
[1615]276    {
[1622]277        if (!this->overlay_)
278            return;
[1595]279
[1622]280        // transform the angle to a range of 0 - pi/2 first.
[1617]281        float angle = this->angle_.valueRadians();
282        if (angle < 0.0)
283            angle = -angle;
[3300]284        angle -= Ogre::Math::PI * static_cast<int>(angle / (Ogre::Math::PI));
[1615]285        if (angle > Ogre::Math::PI * 0.5)
286            angle = Ogre::Math::PI - angle;
[1747]287
[1622]288        // do some mathematical fiddling for a bounding box
[1615]289        Vector2 actualSize = size_ * sizeCorrection_;
290        float radius = actualSize.length();
291        float phi = atan(actualSize.y / actualSize.x);
292        Vector2 boundingBox(radius * cos(angle - phi), radius * sin(angle + phi));
[1622]293
294        // calculate the scrolling offset
295        Vector2 scroll = (position_ - 0.5 - boundingBox * (pickPoint_ - 0.5)) * 2.0;
[1615]296        this->overlay_->setScroll(scroll.x, -scroll.y);
297    }
[1598]298
[1615]299
[1622]300    //########### Console commands ############
301
302    /**
303    @brief
304        Scales an overlay by its name.
305    @param name
306        The name of the overlay defined BaseObject::setName() (usually done with the "name"
[1623]307        attribute in the xml file).
[1622]308    */
[1615]309    /*static*/ void OrxonoxOverlay::scaleOverlay(const std::string& name, float scale)
310    {
311        std::map<std::string, OrxonoxOverlay*>::const_iterator it = overlays_s.find(name);
312        if (it != overlays_s.end())
[6417]313            it->second->scale(Vector2(scale, scale));
[1615]314    }
315
[1622]316    /**
317    @brief
[2993]318        Toggles the visibility of an Overlay by it's name.
319    @param name
320        The name of the overlay defined BaseObject::setName() (usually done with the "name"
321        attribute in the xml file).
322    */
323    /*static*/ void OrxonoxOverlay::toggleVisibility(const std::string& name)
324    {
325        std::map<std::string, OrxonoxOverlay*>::const_iterator it = overlays_s.find(name);
326        if (it != overlays_s.end())
327        {
[6417]328            OrxonoxOverlay* overlay= it->second;
[2993]329            if(overlay->isVisible())
[6711]330            {
[2993]331                overlay->hide();
[6799]332                COUT(4) << "HIDE " << name << std::endl;
[6711]333            }
[2993]334            else
[6711]335            {
[2993]336                overlay->show();
[6799]337                COUT(4) << "SHOW " << name << std::endl;
[6711]338            }
[2993]339        }
340    }
341
342    /**
343    @brief
[1622]344        Scrolls an overlay by its name.
345    @param name
346        The name of the overlay defined BaseObject::setName() (usually done with the "name"
[1623]347        attribute in the xml file).
[1622]348    */
[1615]349    /*static*/ void OrxonoxOverlay::scrollOverlay(const std::string& name, const Vector2& scroll)
350    {
351        std::map<std::string, OrxonoxOverlay*>::const_iterator it = overlays_s.find(name);
352        if (it != overlays_s.end())
[6417]353            it->second->scroll(scroll);
[1615]354    }
355
[1622]356    /**
357    @brief
358        Rotates an overlay by its name.
359    @param name
360        The name of the overlay defined BaseObject::setName() (usually done with the "name"
[1623]361        attribute in the xml file).
[1622]362    */
[1615]363    /*static*/ void OrxonoxOverlay::rotateOverlay(const std::string& name, const Degree& angle)
364    {
365        std::map<std::string, OrxonoxOverlay*>::const_iterator it = overlays_s.find(name);
366        if (it != overlays_s.end())
[6417]367            it->second->rotate(angle);
[1615]368    }
[6057]369
370    void OrxonoxOverlay::setOverlayGroup(OverlayGroup* group)
371    {
372        if (group != this->group_)
373        {
374            if (this->group_)
375                this->group_->removeElement(this);
376            this->group_ = group;
377            this->changedOverlayGroup();
378        }
379    }
[6417]380
381    void OrxonoxOverlay::setBackgroundAlpha(float alpha) {
382        Ogre::MaterialPtr ptr = this->background_->getMaterial();
383        Ogre::TextureUnitState* tempTx = ptr->getTechnique(0)->getPass(0)->getTextureUnitState(0);
384        tempTx->setAlphaOperation(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, alpha);
385    }
[1588]386}
Note: See TracBrowser for help on using the repository browser.