Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/overlays/OrxonoxOverlay.cc @ 8351

Last change on this file since 8351 was 8351, checked in by rgrieder, 13 years ago

Merged kicklib2 branch back to trunk (includes former branches ois_update, mac_osx and kicklib).

Notes for updating

Linux:
You don't need an extra package for CEGUILua and Tolua, it's already shipped with CEGUI.
However you do need to make sure that the OgreRenderer is installed too with CEGUI 0.7 (may be a separate package).
Also, Orxonox now recognises if you install the CgProgramManager (a separate package available on newer Ubuntu on Debian systems).

Windows:
Download the new dependency packages versioned 6.0 and use these. If you have problems with that or if you don't like the in game console problem mentioned below, you can download the new 4.3 version of the packages (only available for Visual Studio 2005/2008).

Key new features:

  • *Support for Mac OS X*
  • Visual Studio 2010 support
  • Bullet library update to 2.77
  • OIS library update to 1.3
  • Support for CEGUI 0.7 —> Support for Arch Linux and even SuSE
  • Improved install target
  • Compiles now with GCC 4.6
  • Ogre Cg Shader plugin activated for Linux if available
  • And of course lots of bug fixes

There are also some regressions:

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