Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/tutoriallevel2/src/modules/notifications/NotificationQueue.cc @ 8371

Last change on this file since 8371 was 8371, checked in by dafrick, 14 years ago

Merging tutoriallevel branch into tutoriallevel2 branch.

  • Property svn:eol-style set to native
File size: 15.3 KB
RevLine 
[2280]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 *      Damian 'Mozork' Frick
24 *   Co-authors:
25 *      ...
26 *
27 */
28
[2911]29/**
[7403]30    @file NotificationQueue.cc
[2911]31    @brief Implementation of the NotificationQueue class.
32*/
33
[2280]34#include "NotificationQueue.h"
35
[7403]36#include <map>
37#include <sstream>
38
39#include "core/CoreIncludes.h"
[7488]40#include "core/GameMode.h"
[7403]41#include "core/GUIManager.h"
42#include "core/LuaState.h"
[7163]43#include "util/Convert.h"
[7403]44#include "util/SubString.h"
[2280]45
[7403]46#include "Notification.h"
47
[2435]48namespace orxonox
49{
[2910]50
[2911]51    /**
52    @brief
53        Constructor. Creates and initializes the object.
[7403]54    @param name
[7484]55        The name of the new NotificationQueue. It needs to be unique
[7403]56    @param senders
57        The senders that are targets of this NotificationQueue, i.e. the names of senders whose Notifications this NotificationQueue displays.
58        The senders need to be seperated by commas.
59    @param size
60        The size (the maximum number of displayed Notifications) of this NotificationQueue.
61    @param displayTime
62        The time during which a Notification is (at most) displayed.
[2911]63    */
[7403]64    NotificationQueue::NotificationQueue(const std::string& name, const std::string& senders, unsigned int size, unsigned int displayTime)
[2280]65    {
[7163]66        this->registered_ = false;
67
[7403]68        RegisterRootObject(NotificationQueue);
[2911]69
[7403]70        // Initialize.
[2911]71        this->size_ = 0;
[7413]72        this->tickTime_ = 0.0f;
[2911]73
[7403]74        // Sets the input values.
75        this->setTargets(senders);
76        this->name_ = name;
77        this->maxSize_ = size;
78        this->setDisplayTime(displayTime);
79
80        // Register the NotificationQueue with the NotificationManager.
81        bool queueRegistered = NotificationManager::getInstance().registerQueue(this);
[7163]82        this->registered_ = true;
[7403]83        if(!queueRegistered) // If the registration has failed.
84        {
85            this->registered_ = false;
[7413]86            COUT(1) << "Error: NotificationQueue '" << this->getName() << "' could not be registered." << std::endl;
[7403]87            return;
88        }
89
90        this->create(); // Creates the NotificationQueue in lua.
91
[7489]92        // Register the NotificationQueue as NotificationListener with the NotificationManager.
[7403]93        bool listenerRegistered = NotificationManager::getInstance().registerListener(this);
94        if(!listenerRegistered) // If the registration has failed.
95        {
96            this->registered_ = false;
97            // Remove the NotificationQueue in lua.
[7489]98            if(GameMode::showsGraphics())
99                GUIManager::getInstance().getLuaState()->doString("NotificationLayer.removeQueue(\"" + this->getName() +  "\")");
[7403]100            NotificationManager::getInstance().unregisterQueue(this);
[7413]101            COUT(1) << "Error: NotificationQueue '" << this->getName() << "' could not be registered." << std::endl;
[7403]102            return;
103        }
104
105        COUT(3) << "NotificationQueue '" << this->getName() << "' created." << std::endl;
[2911]106    }
107
108    /**
109    @brief
[7403]110        Destructor.
[2911]111    */
[7403]112    NotificationQueue::~NotificationQueue()
[2911]113    {
[7403]114        this->targets_.clear();
[2911]115
[7488]116        if(this->registered_) // If the NotificationQueue is registered.
[7403]117        {
[7488]118            this->clear(true);
[2911]119
[7403]120            // Unregister with the NotificationManager.
121            NotificationManager::getInstance().unregisterListener(this);
122            NotificationManager::getInstance().unregisterQueue(this);
[7488]123        }
124    }
[7403]125
[7488]126    /**
127    @brief
128        Destroys the NotificationQueue.
129        Used in lua and NotificationManager.
130    @param noGraphics
131        If this is set to true (false is default), then the queue is not removed in lua. This is used to destroy the queue, after the GUIManager has been destroyed.
132    */
133    void NotificationQueue::destroy(bool noGraphics)
134    {
135        // Remove the NotificationQueue in lua.
136        if(GameMode::showsGraphics() && !noGraphics)
[7403]137            GUIManager::getInstance().getLuaState()->doString("NotificationLayer.removeQueue(\"" + this->getName() +  "\")");
[7488]138
[8079]139        COUT(3) << "NotificationQueue '" << this->getName() << "' destroyed." << std::endl;
140
[7488]141        this->OrxonoxClass::destroy();
[2911]142    }
143
144    /**
145    @brief
[7403]146        Creates the NotificationQueue in lua.
[2911]147    */
[7403]148    void NotificationQueue::create(void)
[2911]149    {
[7488]150        if(GameMode::showsGraphics())
151            GUIManager::getInstance().getLuaState()->doString("NotificationLayer.createQueue(\"" + this->getName() +  "\", " + multi_cast<std::string>(this->getMaxSize()) + ")");
[2911]152    }
153
154    /**
155    @brief
156        Updates the queue from time to time.
157    @param dt
158        The time interval that has passed since the last tick.
159    */
160    void NotificationQueue::tick(float dt)
161    {
[7403]162        this->tickTime_ += dt; // Add the time interval that has passed to the time counter.
[8371]163        if(this->displayTime_ != INF && this->tickTime_ >= 1.0) // If the time counter is greater than 1s all Notifications that have expired are removed, if it is smaller we wait to the next tick.
[2910]164        {
[7403]165            this->timeLimit_.time = std::time(0)-this->displayTime_; // Container containig the current time.
[2911]166
[7403]167            std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator it = this->ordering_.begin();
168            // Iterate through all elements whose creation time is smaller than the current time minus the display time.
[7410]169            while(it != this->ordering_.upper_bound(&this->timeLimit_))
[2911]170            {
[8079]171                this->remove(it); // Remove the Notifications that have expired.
172                it = this->ordering_.begin();
[2911]173            }
174
[7403]175            this->tickTime_ = this->tickTime_ - (int)this->tickTime_; // Reset time counter.
[2910]176        }
[2911]177    }
178
179    /**
180    @brief
181        Updates the NotificationQueue.
[7403]182        Updates by clearing the queue and requesting all relevant Notifications from the NotificationManager and inserting them into the queue.
[2911]183    */
184    void NotificationQueue::update(void)
185    {
186        this->clear();
187
[7403]188        std::multimap<std::time_t, Notification*>* notifications = new std::multimap<std::time_t, Notification*>;
189        // Get the Notifications sent in the interval from now to now minus the display time.
[8371]190        if(this->displayTime_ == INF)
191            NotificationManager::getInstance().getNewestNotifications(this, notifications, this->getMaxSize());
192        else
193            NotificationManager::getInstance().getNotifications(this, notifications, this->displayTime_);
[2910]194
[7403]195        if(!notifications->empty())
[2911]196        {
[7403]197            // Add all Notifications.
198            for(std::multimap<std::time_t, Notification*>::iterator it = notifications->begin(); it != notifications->end(); it++)
199                this->push(it->second, it->first);
[2911]200        }
201
202        delete notifications;
203
[7163]204        COUT(4) << "NotificationQueue '" << this->getName() << "' updated." << std::endl;
[2280]205    }
[2910]206
[2911]207    /**
208    @brief
209        Updates the NotificationQueue by adding an new Notification.
210    @param notification
211        Pointer to the Notification.
212    @param time
213        The time the Notification was sent.
214    */
215    void NotificationQueue::update(Notification* notification, const std::time_t & time)
[2280]216    {
[7489]217        assert(notification);
218
[7403]219        this->push(notification, time);
[2910]220
[7403]221        COUT(4) << "NotificationQueue '" << this->getName() << "' updated. A new Notification has been added." << std::endl;
[2280]222    }
[2910]223
[2911]224    /**
225    @brief
[7403]226        Adds (pushes) a Notification to the NotificationQueue.
227        It inserts it into the storage containers, creates a corresponding container and pushes the Notification message to the GUI.
228    @param notification
229        The Notification to be pushed.
230    @param time
231        The time when the Notification has been sent.
[2911]232    */
[7403]233    void NotificationQueue::push(Notification* notification, const std::time_t & time)
[2280]234    {
[7489]235        assert(notification);
236
[7403]237        NotificationContainer* container = new NotificationContainer;
238        container->notification = notification;
239        container->time = time;
240
241        // If the maximum size of the NotificationQueue has been reached the last (least recently added) Notification is removed.
242        if(this->getSize() >= this->getMaxSize())
243            this->pop();
244
245        this->size_++;
246
247        this->ordering_.insert(container);
248        // Insert the Notification at the begin of the list (vector, actually).
249        this->notifications_.insert(this->notifications_.begin(), container);
250
251        // Push the Notification to the GUI.
[7488]252        if(GameMode::showsGraphics())
253            GUIManager::getInstance().getLuaState()->doString("NotificationLayer.pushNotification(\"" + this->getName() + "\", \"" + notification->getMessage() + "\")");
[8079]254
255        COUT(5) << "Notification \"" << notification->getMessage() << "\" pushed to NotificationQueue '" << this->getName() << "'" << endl;
[2911]256    }
[2500]257
[2911]258    /**
259    @brief
[7403]260        Removes (pops) the least recently added Notification form the NotificationQueue.
[2911]261    */
[7403]262    void NotificationQueue::pop(void)
[2911]263    {
[7403]264        NotificationContainer* container = this->notifications_.back();
[7412]265        // Get all the NotificationContainers that were sent the same time the NotificationContainer we want to pop was sent.
266        std::pair<std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator, std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator> iterators = this->ordering_.equal_range(container);
[8079]267
[7489]268        // Iterate through all suspects and remove the container as soon as we find it.
[7412]269        for(std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator it = iterators.first; it != iterators.second; it++)
270        {
271            if(container == *it)
272            {
[8079]273                COUT(5) << "Notification \"" << (*it)->notification->getMessage() << "\" popped from NotificationQueue '" << this->getName() << "'" << endl;
[7412]274                this->ordering_.erase(it);
275                break;
276            }
277        }
[7403]278        this->notifications_.pop_back();
[2910]279
[7403]280        this->size_--;
281
282        delete container;
283
284        // Pops the Notification from the GUI.
[7488]285        if(GameMode::showsGraphics())
286            GUIManager::getInstance().getLuaState()->doString("NotificationLayer.popNotification(\"" + this->getName() + "\")");
[2911]287    }
[2910]288
[2911]289    /**
290    @brief
[7403]291        Removes the Notification that is stored in the input NotificationContainer.
[7412]292    @param containerIterator
293        An iterator to the NotificationContainer to be removed.
[2911]294    */
[7412]295    void NotificationQueue::remove(const std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator& containerIterator)
[2911]296    {
[7412]297        std::vector<NotificationContainer*>::iterator it = std::find(this->notifications_.begin(), this->notifications_.end(), *containerIterator);
[7403]298        // Get the index at which the Notification is.
299        std::vector<NotificationContainer*>::difference_type index = it - this->notifications_.begin ();
[8079]300
301        COUT(5) << "Notification \"" << (*it)->notification->getMessage() << "\" removed from NotificationQueue '" << this->getName() << "'" << endl;
302
[7412]303        this->ordering_.erase(containerIterator);
[7403]304        this->notifications_.erase(it);
[2911]305
[7403]306        this->size_--;
307
[7412]308        delete *containerIterator;
[7403]309
310        // Removes the Notification from the GUI.
[7488]311        if(GameMode::showsGraphics())
312            GUIManager::getInstance().getLuaState()->doString("NotificationLayer.removeNotification(\"" + this->getName() + "\", " + multi_cast<std::string>(index) + ")");
[2909]313    }
[2500]314
[2911]315    /**
316    @brief
[7403]317        Clears the NotificationQueue by removing all NotificationContainers.
[7488]318    @param noGraphics
319        If this is eset to true the GUI is not informed of the clearing of the NotificationQueue. This is needed only internally.
[2911]320    */
[7488]321    void NotificationQueue::clear(bool noGraphics)
[2280]322    {
[8079]323        COUT(4) << "Clearing NotificationQueue " << this->getName() << "." << endl;
[7403]324        this->ordering_.clear();
325        // Delete all NotificationContainers in the list.
326        for(std::vector<NotificationContainer*>::iterator it = this->notifications_.begin(); it != this->notifications_.end(); it++)
327            delete *it;
[2911]328
[7403]329        this->notifications_.clear();
330        this->size_ = 0;
[2500]331
[7403]332        // Clear the NotificationQueue in the GUI.
[7488]333        if(GameMode::showsGraphics() && !noGraphics)
334            GUIManager::getInstance().getLuaState()->doString("NotificationLayer.clearQueue(\"" + this->getName() + "\")");
[2346]335    }
[2500]336
[2911]337    /**
338    @brief
[7403]339        Sets the name of the NotificationQueue.
340    @param name
341        The name to be set.
[2911]342    */
[7403]343    void NotificationQueue::setName(const std::string& name)
[2280]344    {
[7403]345        this->name_ = name;
[2280]346    }
[2500]347
[2911]348    /**
349    @brief
[7403]350        Sets the maximum number of displayed Notifications.
351    @param size
352        The size to be set.
[2911]353    */
[7403]354    void NotificationQueue::setMaxSize(unsigned int size)
[2280]355    {
[7403]356        if(this->maxSize_ == size)
357            return;
[2911]358
[7403]359        this->maxSize_ = size;
360
361        if(this->registered_)
362            this->update();
[2911]363    }
364
365    /**
366    @brief
[7403]367        Sets the maximum number of seconds a Notification is displayed.
[2911]368    @param time
[8371]369        The number of seconds a Notification is displayed.
[2911]370    */
[8371]371    void NotificationQueue::setDisplayTime(int time)
[2911]372    {
[7403]373        if(this->displayTime_ == time)
374            return;
[2911]375
[7403]376        this->displayTime_ = time;
[2911]377
[7403]378        if(this->registered_)
379            this->update();
[2911]380    }
381
382    /**
383    @brief
[8079]384        Produces all targets of the NotificationQueue concatinated as string, with commas (',') as seperators.
[2911]385    @return
[7403]386        Returns the targets as a string.
[2911]387    */
[7403]388    const std::string& NotificationQueue::getTargets(void) const
[2911]389    {
[7403]390        std::stringstream stream;
391        bool first = true;
392        // Iterate through the set of targets.
[7417]393        for(std::set<std::string>::const_iterator it = this->targets_.begin(); it != this->targets_.end(); it++)
[7403]394        {
395            if(!first)
396                stream << ", ";
397            else
398                first = false;
399            stream << *it;
400        }
[2911]401
[7403]402        return *(new std::string(stream.str()));
[2911]403    }
404
405    /**
406    @brief
[7403]407        Sets the targets of the NotificationQueue.
408        The targets are the senders whose Notifications are displayed in this queue.
409    @param targets
410        Accepts a string of targets, each seperated by commas (','), spaces are ignored.
[2911]411    */
[7403]412    void NotificationQueue::setTargets(const std::string & targets)
[2911]413    {
[7403]414        this->targets_.clear();
415
416        SubString string = SubString(targets, ",", " ", false);
417        for(unsigned int i = 0; i < string.size(); i++)
418            this->targets_.insert(string[i]);
419
420        if(this->registered_)
[2911]421        {
[7403]422            NotificationManager::getInstance().unregisterListener(this);
423            NotificationManager::getInstance().registerListener(this);
[2911]424        }
425    }
426
[2280]427}
[7403]428
Note: See TracBrowser for help on using the repository browser.