Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/tutoriallevel2/src/modules/notifications/NotificationManager.cc @ 8374

Last change on this file since 8374 was 8374, checked in by dafrick, 13 years ago

Changes in notifications module structure. Notifications can now be sent through the NotificationListener, meaning, they can be sent from anywhere within orxonox (and the modules of course).

  • Property svn:eol-style set to native
File size: 16.0 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 *      Damian 'Mozork' Frick
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30    @file NotificationManager.cc
31    @brief Implementation of the NotificationManager class.
32*/
33
34#include "NotificationManager.h"
35
36#include "core/command/ConsoleCommand.h"
37#include "core/CoreIncludes.h"
38#include "core/GameMode.h"
39#include "core/GUIManager.h"
40#include "core/LuaState.h"
41#include "util/Convert.h"
42#include "util/ScopedSingletonManager.h"
43
44#include "interfaces/NotificationListener.h"
45
46#include "Notification.h"
47#include "NotificationQueue.h"
48
49#include "ToluaBindNotifications.h"
50
51namespace orxonox
52{
53
54    // Register tolua_open function when loading the library.
55    DeclareToluaInterface(Notifications);
56
57    ManageScopedSingleton(NotificationManager, ScopeID::Root, false);
58
59    // Setting console command to enter the edit mode.
60    SetConsoleCommand("enterEditMode", &NotificationManager::enterEditMode);
61
62    /**
63    @brief
64        Constructor. Registers the Object.
65    */
66    NotificationManager::NotificationManager()
67    {
68        RegisterRootObject(NotificationManager);
69
70        ModifyConsoleCommand("enterEditMode").setObject(this);
71
72        COUT(3) << "NotificatioManager created." << std::endl;
73    }
74
75    /**
76    @brief
77        Destructor.
78    */
79    NotificationManager::~NotificationManager()
80    {
81        ModifyConsoleCommand("enterEditMode").setObject(NULL);
82
83        // Destroys all Notifications.
84        for(std::multimap<std::time_t, Notification*>::iterator it = this->allNotificationsList_.begin(); it!= this->allNotificationsList_.end(); it++)
85            it->second->destroy();
86        this->allNotificationsList_.clear();
87
88        COUT(3) << "NotificationManager destroyed." << std::endl;
89    }
90
91    /**
92    @brief
93        Is called before the object is destroyed.
94    */
95    void NotificationManager::preDestroy(void)
96    {
97        // Destroys all NotificationQueues that have been registered with the NotificationManager.
98        std::map<const std::string, NotificationQueue*>::iterator it = this->queues_.begin();
99        while(it != this->queues_.end())
100        {
101            it->second->destroy(true);
102            it = this->queues_.begin();
103        }
104
105        this->queues_.clear();
106    }
107   
108    bool NotificationManager::registerNotification(const std::string& message, const std::string& sender)
109    {
110        Notification* notification = new Notification(message, sender);
111        return this->registerNotification(notification);
112    }
113
114    /**
115    @brief
116        Registers a Notification within the NotificationManager and makes sure that the Notification is sent to all the NotificationQueues associated with its sender.
117    @param notification
118        The Notification to be registered.
119    @return
120        Returns true if successful.
121    */
122    bool NotificationManager::registerNotification(Notification* notification)
123    {
124        assert(notification);
125
126        std::time_t time = std::time(0); // Get current time.
127
128        // Add the Notification to the list that holds all Notifications.
129        this->allNotificationsList_.insert(std::pair<std::time_t, Notification*>(time, notification));
130
131        if(notification->getSender() == NotificationListener::NONE) // If the sender has no specific name, then the Notification is only added to the list of all Notifications.
132            return true;
133
134        bool all = false;
135        if(notification->getSender() == NotificationListener::ALL) // If all are the sender, then the Notifications is added to every NotificationQueue.
136            all = true;
137
138        // Insert the Notification in all NotificationQueues that have its sender as target.
139        for(std::map<const std::string, NotificationQueue*>::iterator it = this->queues_.begin(); it != this->queues_.end(); it++) // Iterate through all NotificationQueues.
140        {
141            const std::set<std::string>& set = it->second->getTargetsSet();
142            bool bAll = set.find(NotificationListener::ALL) != set.end();
143            // If either the Notification has as sender 'all', the NotificationQueue displays all Notifications or the NotificationQueue has the sender of the Notification as target.
144            if(all || bAll || set.find(notification->getSender()) != set.end())
145            {
146                if(!bAll)
147                    this->notificationLists_[it->second->getName()]->insert(std::pair<std::time_t, Notification*>(time, notification)); // Insert the Notification in the notifications list of the current NotificationQueue.
148                it->second->update(notification, time); // Update the NotificationQueue.
149            }
150        }
151
152        COUT(4) << "Notification (&" << notification << ") registered with the NotificationManager." << std::endl;
153
154        return true;
155    }
156
157    /**
158    @brief
159        Unregisters a Notification within the NotificationManager for a given NotificationQueue.
160    @param notification
161        A pointer to the Notification to be unregistered.
162    @param queue
163        A pointer to the NotificationQueue the Notification is unregistered for.
164    */
165    void NotificationManager::unregisterNotification(Notification* notification, NotificationQueue* queue)
166    {
167        assert(notification);
168        assert(queue);
169
170        // Remove the Notification from the list of Notifications of the input NotificationQueue.
171        this->removeNotification(notification, *(this->notificationLists_.find(queue->getName())->second));
172
173        COUT(4) << "Notification (&" << notification << ") unregistered with the NotificationManager from NotificationQueue " << queue->getName() << "." << std::endl;
174    }
175
176    /**
177    @brief
178        Helper method that removes an input Notification form an input map.
179    @param notification
180        A pointer to the Notification to be removed.
181    @param map
182        The map the Notification should be removed from.
183    @return
184        Returns true if successful.
185    */
186    bool NotificationManager::removeNotification(Notification* notification, std::multimap<std::time_t, Notification*>& map)
187    {
188        // Iterates through all items in the map until the Notification is found.
189        //TODO: Do more efficiently?
190        for(std::multimap<std::time_t, Notification*>::iterator it = map.begin(); it != map.end(); it++)
191        {
192            if(it->second == notification)
193            {
194                map.erase(it);
195                return true;
196            }
197        }
198        return false;
199    }
200
201    /**
202    @brief
203        Fetches the Notifications for a specific NotificationQueue in a specified timeframe and stores them in the input map.
204    @param queue
205        The NotificationQueue the Notifications are fetched for.
206    @param map
207        A pointer to a multimap, in which the notifications are stored. The map needs to have been allocated.
208    @param timeFrameStart
209        The start time of the timeframe.
210    @param timeFrameEnd
211        The end time of the timeframe.
212    @return
213        Returns true if successful.
214    */
215    void NotificationManager::getNotifications(NotificationQueue* queue, std::multimap<std::time_t,Notification*>* map, const std::time_t & timeFrameStart, const std::time_t & timeFrameEnd)
216    {
217        assert(queue);
218        assert(map);
219
220        std::multimap<std::time_t, Notification*>* notifications = this->notificationLists_[queue->getName()]; // All the Notifications for the input NotificationQueue.
221
222        std::multimap<std::time_t,Notification*>::iterator it, itLowest, itHighest;
223        // Iterators pointing to the bounds specified by the specified start and end times of the time frame.
224        itLowest = notifications->lower_bound(timeFrameStart);
225        itHighest = notifications->upper_bound(timeFrameEnd);
226
227        for(it = itLowest; it != itHighest; it++) // Iterate through the Notifications from the start of the time frame to the end of it.
228            map->insert(std::pair<std::time_t, Notification*>(it->first, it->second)); // Add the found Notifications to the map.
229    }
230
231    /**
232    @brief
233        Fetches the newest Notifications for a specific NotificationQueue and stores them in the input map.
234    @param queue
235        The NotificationQueue the Notifications are fetched for.
236    @param map
237        A pointer to a multimap, in which the notifications are stored. The map needs to have been allocated.
238    @param numberOfNotifications
239        The number of newest Notifications to be got.
240    @return
241        Returns true if successful.
242    */
243    void NotificationManager::getNewestNotifications(NotificationQueue* queue, std::multimap<std::time_t, Notification*>* map, int numberOfNotifications)
244    {
245        assert(queue);
246        assert(map);
247
248        std::multimap<std::time_t, Notification*>* notifications = this->notificationLists_[queue->getName()]; // All the Notifications for the input NotificationQueue.
249
250        if(!notifications->empty()) // If the list of Notifications is not empty.
251        {
252            std::multimap<std::time_t,Notification*>::iterator it = notifications->end();
253            for(int i = 0; i < numberOfNotifications; i++) // Iterate through the Notifications from the newest until we have the specified number of notifications.
254            {
255                it--;
256                map->insert(std::pair<std::time_t, Notification*>(it->first, it->second)); // Add the found Notifications to the map.
257                if(it == notifications->begin())
258                    break;
259            }
260        }
261    }
262
263    /**
264    @brief
265        Enters the edit mode of the NotificationLayer.
266    */
267    void NotificationManager::enterEditMode(void)
268    {
269        if(GameMode::showsGraphics())
270        {
271            GUIManager::getInstance().hideGUI("NotificationLayer");
272            GUIManager::getInstance().showGUI("NotificationLayer", false, false);
273            GUIManager::getInstance().getLuaState()->doString("NotificationLayer.enterEditMode()");
274        }
275    }
276
277    /**
278    @brief
279        Registers a NotificationQueue.
280        This makes sure that the NotificationQueue can be accessed through lua by name. It also makes sure that the NotificationQueue is destroyed upon destruction of the NotificationManager.
281    @param queue
282        A pointer to the NotificationQueue to be registered.
283    @return
284        Returns true if successful. If e.g. the a NotificationQueue with that name already exists this returns false.
285    */
286    bool NotificationManager::registerQueue(NotificationQueue* queue)
287    {
288        assert(queue);
289
290        // If the NotificationQueue is already registered.
291        if(this->queues_.find(queue->getName()) != this->queues_.end())
292            return false;
293
294        this->queues_.insert(std::pair<const std::string, NotificationQueue*>(queue->getName(), queue)); // Add the NotificationQueue to the list of NotificationQueues.
295
296        const std::set<std::string>& set = queue->getTargetsSet();
297
298        // If all senders are the target of the NotificationQueue, then the list of Notifications for that specific NotificationQueue is the same as the list of all Notifications.
299        bool bAll = set.find(NotificationListener::ALL) != set.end();
300        std::multimap<std::time_t, Notification*>* map = NULL;
301        if(bAll)
302            this->notificationLists_[queue->getName()] = &this->allNotificationsList_;
303        // Else a new list (resp. multimap) is created and added to the list of Notification lists for NotificationQueues.
304        else
305        {
306            this->notificationLists_[queue->getName()] = new std::multimap<std::time_t, Notification*>;
307            map = this->notificationLists_[queue->getName()];
308        }
309
310        // Iterate through all Notifications to determine whether any of them should belong to the newly registered NotificationQueue.
311        for(std::multimap<std::time_t, Notification*>::iterator it = this->allNotificationsList_.begin(); it != this->allNotificationsList_.end(); it++)
312        {
313            if(!bAll && set.find(it->second->getSender()) != set.end()) // Checks whether the listener has the sender of the current Notification as target.
314                map->insert(std::pair<std::time_t, Notification*>(it->first, it->second));
315        }
316
317        queue->update(); // Update the queue.
318       
319        COUT(4) << "NotificationQueue '" << queue->getName() << "' registered with the NotificationManager." << std::endl;
320        return true;
321    }
322
323    /**
324    @brief
325        Unregisters a NotificationQueue.
326    @param queue
327        A pointer to the NotificationQueue to be unregistered.
328    */
329    void NotificationManager::unregisterQueue(NotificationQueue* queue)
330    {
331        assert(queue);
332
333        std::multimap<std::time_t, Notification*>* map = this->notificationLists_.find(queue->getName())->second;
334
335        // If the map is not the map of all Notifications, make sure all Notifications are unregistered.
336        std::multimap<std::time_t, Notification*>::iterator it = map->begin();
337        if(map != &this->allNotificationsList_)
338        {
339            while(it != map->end())
340            {
341                this->unregisterNotification(it->second, queue);
342                it = map->begin();
343            }
344            delete map;
345        }
346
347        // Remove the NotificationQueue from the list of NotificationQueues.
348        this->queues_.erase(queue->getName());
349        // Remove the Notifications list that was associated with the input NotificationQueue.
350        this->notificationLists_.erase(queue->getName());
351       
352        COUT(4) << "NotificationQueue '" << queue->getName() << "' unregistered with the NotificationManager." << std::endl;
353    }
354
355    /**
356    @brief
357        Loads all the NotificationQueues that should exist.
358    */
359    void NotificationManager::loadQueues(void)
360    {
361        NotificationQueue* allQueue = new NotificationQueue("all");
362        GUIManager::getInstance().getLuaState()->doString("NotificationLayer.resizeQueue(\"all\", 0.5, 0, " + multi_cast<std::string>(allQueue->getMaxSize()) + ")");
363        GUIManager::getInstance().getLuaState()->doString("NotificationLayer.moveQueue(\"all\", 0, 10, 0.3, 0)");
364
365        NotificationQueue* infoQueue = new NotificationQueue("info", NotificationListener::ALL, 1, -1);
366        GUIManager::getInstance().getLuaState()->doString("NotificationLayer.changeQueueFont(\"info\", 24, \"FFFFFF00\")");
367        GUIManager::getInstance().getLuaState()->doString("NotificationLayer.resizeQueue(\"info\", 0.6, 0, " + multi_cast<std::string>(infoQueue->getMaxSize()) + ")");
368        GUIManager::getInstance().getLuaState()->doString("NotificationLayer.moveQueue(\"info\", 0.2, 0, 0.8, 0)");
369    }
370
371    /**
372    @brief
373        Creates a new NotificationQueue.
374        This is used in lua.
375    @param name
376        The name of the new NotificationQueue.
377    */
378    void NotificationManager::createQueue(const std::string& name)
379    {
380        new NotificationQueue(name);
381    }
382
383    /**
384    @brief
385        Get the NotificationQueue with the input name.
386    @param name
387        The name of the NotificationQueue.
388    @return
389        Returns a pointer to the NotificationQueue with the input name. Returns NULL if no NotificationQueue with such a name exists.
390    */
391    NotificationQueue* NotificationManager::getQueue(const std::string & name)
392    {
393        std::map<const std::string, NotificationQueue*>::iterator it = this->queues_.find(name);
394        // Returns NULL if no such NotificationQueue exists.
395        if(it == this->queues_.end())
396            return NULL;
397
398        return (*it).second;
399    }
400
401}
Note: See TracBrowser for help on using the repository browser.