Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation3/src/modules/questsystem/QuestGUINode.cc @ 7038

Last change on this file since 7038 was 6945, checked in by dafrick, 15 years ago

A lot of cleanup, mostly increasing output levels, which means, that the console is no longer cluttered by lots and lots of Quest-stuff (the log file still is, but that should be ok…).
Also some possible bugs (or let's say pitfalls) removed, which have been around for a long time and didn't cause any problems so far. Now they never will.
Also, regarding my previous commit. Quests seem tu work just fine, even the second time the level is loaded, which is awesome.

Ergo: Questsystem/Notificationsystem segfault upon loading a level with Quests/Notifications in it twice is now officially resolved.

  • Property svn:eol-style set to native
File size: 14.9 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#include "QuestGUINode.h"
30
31#include <sstream>
32
33#include <CEGUIWindowManager.h>
34#include <elements/CEGUIFrameWindow.h>
35#include <elements/CEGUIPushButton.h>
36#include <falagard/CEGUIFalWidgetLookFeel.h>
37#include <falagard/CEGUIFalWidgetLookManager.h>
38
39#include "core/CoreIncludes.h"
40#include "Quest.h"
41#include "QuestHint.h"
42#include "QuestItem.h"
43#include "QuestDescription.h"
44#include "QuestGUI.h"
45
46namespace orxonox {
47
48    /**
49    @brief
50        Default Constructor. Registers and initializes the object.
51    */
52    QuestGUINode::QuestGUINode(void)
53    {
54        this->initialize();
55    }
56
57    /**
58    @brief
59        Constructor. Registers and initializes the object.
60    @param gui
61        The QuestGUi the node beongs to.
62    @param parent
63        The parent node of the newly created node.
64    @param item
65        The QuestItem the  newly created node is for.
66    @param depth
67        Parameter to define how much the list item has to be indented.
68    @param index
69        "Counter" for Quests and Hints.
70    */
71    QuestGUINode::QuestGUINode(QuestGUI* gui, QuestGUINode* parent, QuestItem* item, int depth, int index)
72    {
73        this->initialize();
74
75        this->gui_ = gui;
76        this->parent_ = parent;
77        this->item_ = item;
78        this->depth_ = depth;
79        this->index_ = index;
80
81        this->createWindow();
82
83        COUT(4) << "New QuestGUINode '" << this->window_->getName() << "' created." << std::endl;
84    }
85
86    /**
87    @brief
88        Destructor.
89    @todo
90        Destroying everything?
91    */
92    QuestGUINode::~QuestGUINode(void)
93    {
94        if(this->window_ != NULL)
95            this->window_->destroy();
96        if(this->details_ != NULL)
97        {
98            this->details_->destroy();
99        }
100    }
101
102    /**
103    @brief
104        Initialize the object.
105    */
106    void QuestGUINode::initialize(void)
107    {
108        RegisterRootObject(QuestGUINode);
109
110        this->parent_ = NULL;
111        this->item_ = NULL;
112        this->window_ = NULL;
113        this->details_ = NULL;
114        this->depth_ = 0;
115        this->index_ = 0;
116        this->visible_ = true;
117    }
118
119    void QuestGUINode::toggleVisibility(void)
120    {
121
122    }
123
124    /**
125    @brief
126        Sets the input buffer to the name of the node.
127    @param buffer
128        The buffer that is set to the name of the node.
129    @todo
130        Needed?
131    */
132    void QuestGUINode::getName(std::string & buffer)
133    {
134        if(this->window_ != NULL)
135        {
136            buffer = this->window_->getName().c_str();
137        }
138        else
139        {
140            buffer.erase();
141        }
142    }
143
144    /**
145    @brief
146        Creates the details window.
147    @return
148        Returns the details window.
149    @todo
150        Return necessary?
151    */
152    CEGUI::Window* QuestGUINode::getDetails(void)
153    {
154
155        if(this->details_ == NULL) //!< If the details window was not already created.
156        {
157            std::ostringstream stream;
158
159            //! Create the main window for the details.
160            stream << this->window_->getName() << "/Details";
161            const QuestDescription* description = this->item_->getDescription();
162            this->details_ = this->gui_->getWindowManager()->createWindow("MenuWidgets/FrameWindow", stream.str());
163            this->details_->setSize(CEGUI::UVector2(CEGUI::UDim(0.7f, 0),CEGUI::UDim(0.7f, 0)));
164            this->details_->setPosition(CEGUI::UVector2(CEGUI::UDim(0.1f, 0),CEGUI::UDim(0.1f, 0)));
165            this->details_->setText(description->getTitle());
166            this->details_->setAlpha(1.0);
167            this->details_->setInheritsAlpha(false);
168            this->details_->setProperty("CloseButtonEnabled", "True");
169            this->details_->subscribeEvent(CEGUI::FrameWindow::EventCloseClicked, CEGUI::Event::Subscriber(&QuestGUINode::closeDetails, this));
170
171            //! Create a ScrollablePane.
172            stream << "/Scrollable";
173            CEGUI::Window* window = this->gui_->getWindowManager()->createWindow("MenuWidgets/ScrollablePane", stream.str());
174            window->setSize(CEGUI::UVector2(CEGUI::UDim(1.0, -2*QuestGUINode::BORDER_WIDTH),CEGUI::UDim(1.0, -QuestGUINode::TITLE_HEIGHT)));
175            window->setPosition(CEGUI::UVector2(CEGUI::UDim(0, (float)QuestGUINode::BORDER_WIDTH),CEGUI::UDim(0, (float)QuestGUINode::TITLE_HEIGHT)));
176            this->details_->addChildWindow(window);
177
178            int height;
179            int offset = 0;
180
181            //! Display the status of the QuestItem if it is a Quest.
182            Quest* quest = dynamic_cast<Quest*>(this->item_);
183            if(quest != NULL) //!< If the QuestItem is a Quest
184            {
185                stream.str("");
186                stream << this->details_->getName() << "/Status";
187                CEGUI::Window* statusWindow = this->gui_->getWindowManager()->createWindow("MenuWidgets/StaticText", stream.str());
188                window->addChildWindow(statusWindow);
189                std::string status;
190                if(quest->isActive(this->gui_->getPlayer()))
191                {
192                    status = "This quest is active.";
193                }
194                else if(quest->isCompleted(this->gui_->getPlayer()))
195                {
196                    status = "This quest was completed.";
197                }
198                else if(quest->isFailed(this->gui_->getPlayer()))
199                {
200                    status = "This quest was failed.";
201                }
202                statusWindow->setProperty("HorzFormatting", "WordWrapLeftAligned");
203                statusWindow->setProperty("VertFormatting", "TopAligned");
204                statusWindow->setText(status);
205                statusWindow->setPosition(CEGUI::UVector2(CEGUI::UDim(0, 0),CEGUI::UDim(0, (float)offset)));
206                statusWindow->setSize(CEGUI::UVector2(CEGUI::UDim(1.0, (float)-QuestGUINode::SCROLLBAR_WIDTH),CEGUI::UDim(1.0f, 0)));
207                height = setHeight(statusWindow);
208
209                offset += height;
210            }
211
212            //! Create title pane for the description.
213            stream.str("");
214            stream << this->details_->getName() << "/Description";
215            stream << "/Title";
216            CEGUI::Window* descriptionWindowTitle = this->gui_->getWindowManager()->createWindow("MenuWidgets/StaticText", stream.str());
217            window->addChildWindow(descriptionWindowTitle);
218            descriptionWindowTitle->setProperty("HorzFormatting", "HorzCentred");
219            descriptionWindowTitle->setProperty("VertFormatting", "TopAligned");
220            descriptionWindowTitle->setText("Description:");
221            descriptionWindowTitle->setPosition(CEGUI::UVector2(CEGUI::UDim(0, 0),CEGUI::UDim(0, (float)offset)));
222            descriptionWindowTitle->setSize(CEGUI::UVector2(CEGUI::UDim(1.0f, -QuestGUINode::SCROLLBAR_WIDTH),CEGUI::UDim(1.0f, 0)));
223
224            offset += setHeight(descriptionWindowTitle);
225
226            //! Display the Description of the QuestItem.
227            stream.str("");
228            stream << this->details_->getName() << "/Description";
229            CEGUI::Window* descriptionWindow = this->gui_->getWindowManager()->createWindow("MenuWidgets/StaticText", stream.str());
230            window->addChildWindow(descriptionWindow);
231            descriptionWindow->setProperty("HorzFormatting", "WordWrapLeftAligned");
232            descriptionWindow->setProperty("VertFormatting", "TopAligned");
233            descriptionWindow->setText(description->getDescription());
234            descriptionWindow->setPosition(CEGUI::UVector2(CEGUI::UDim(0, 0),CEGUI::UDim(0, (float)offset)));
235            descriptionWindow->setSize(CEGUI::UVector2(CEGUI::UDim(1.0, (float)-QuestGUINode::SCROLLBAR_WIDTH),CEGUI::UDim(1.0f, 0)));
236            height = setHeight(descriptionWindow);
237
238            offset += height;
239
240            //! Display a list of hints if the QuestItem is a Quest.
241            bool title = true;
242            if(quest != NULL)
243            {
244                for(std::list<QuestGUINode*>::iterator it = this->subNodes_.begin(); it != this->subNodes_.end(); it++)
245                {
246                    if(dynamic_cast<QuestHint*>((*it)->item_) != NULL) //!< If the subNode belongs to a QuestHint.
247                    {
248                        if(title) //!< If no title pane for the QuestHints has been created, create one.
249                        {
250                            stream.str("");
251                            stream << this->details_->getName() << "/Hints/Title";
252                            CEGUI::Window* hintsTitle = this->gui_->getWindowManager()->createWindow("MenuWidgets/StaticText", stream.str());
253                            window->addChildWindow(hintsTitle);
254                            hintsTitle->setProperty("HorzFormatting", "HorzCentred");
255                            hintsTitle->setProperty("VertFormatting", "TopAligned");
256                            hintsTitle->setText("Hints:");
257                            hintsTitle->setPosition(CEGUI::UVector2(CEGUI::UDim(0, 0),CEGUI::UDim(0, (float)offset)));
258                            hintsTitle->setSize(CEGUI::UVector2(CEGUI::UDim(1.0, -QuestGUINode::SCROLLBAR_WIDTH),CEGUI::UDim(1.0, 0)));
259                            offset += setHeight(hintsTitle);;
260                            title = false;
261                        }
262                        QuestGUINode* node = *it;
263                        node->window_->setSize(CEGUI::UVector2(CEGUI::UDim(1.0f, (float)-QuestGUINode::SCROLLBAR_WIDTH),CEGUI::UDim(0, (float)QuestGUINode::BUTTON_HEIGHT)));
264                        node->window_->setPosition(CEGUI::UVector2(CEGUI::UDim(0, 0),CEGUI::UDim(0, (float)offset)));
265                        window->addChildWindow(node->window_);
266                        offset += QuestGUINode::BUTTON_HEIGHT;
267                    }
268                }
269            }
270
271            COUT(4) << "Show Details: " << this->details_->getName() << std::endl;
272        }
273
274        return this->details_;
275    }
276
277    /**
278    @brief
279        Opens the details window for the Quest/QuestHint clicked on.
280    */
281    bool QuestGUINode::openDetails(const CEGUI::EventArgs& e)
282    {
283        COUT(4) << "Open QuestItem..." << std::endl;
284
285        //CEGUI::Window* window = this->gui_->getRootWindow();
286        CEGUI::Window* window = this->gui_->getWindowManager()->getWindow("orxonox/QuestGUI/Background");
287
288        if(window != NULL)
289            window->addChildWindow(this->getDetails());
290
291        return true;
292    }
293
294    /**
295    @brief
296        Close the details window.
297    */
298    bool QuestGUINode::closeDetails(const CEGUI::EventArgs& e)
299    {
300        //CEGUI::Window* window = this->gui_->getRootWindow();
301        CEGUI::Window* window = this->gui_->getWindowManager()->getWindow("orxonox/QuestGUI/Background");
302        window->removeChildWindow(this->details_);
303
304        return true;
305    }
306
307    /**
308    @brief
309        Helper method for setHeight(). Gets the StaticTextArea for an input CEGUI Window.
310    @param window
311        The CEGUI window.
312    @return
313        Returns a CEGUI Rect.
314    */
315    /*static*/ CEGUI::Rect QuestGUINode::getStaticTextArea(const CEGUI::Window* window)
316    {
317        const CEGUI::WidgetLookFeel& lookAndFeel = CEGUI::WidgetLookManager::getSingleton().getWidgetLook(window->getLookNFeel());
318
319        return lookAndFeel.getNamedArea("WithFrameTextRenderArea").getArea().getPixelRect(*window);
320    }
321
322    /**
323    @brief
324        Helper method to adjust the height of an input Window (of type StaticText) to the text it holds.
325    @param window
326        The  CEGUI Window (of type StaticText) for which the height is to be adjusted to the text.
327    @return
328        Returns the set height.
329    */
330    /*static*/ int QuestGUINode::setHeight(CEGUI::Window* window)
331    {
332        //! Get the area the text is formatted and drawn into.
333        const CEGUI::Rect formattedArea = getStaticTextArea(window);
334
335        //! Calculate the pixel height of the frame by subtracting the height of the area above from the total height of the window.
336        const float frameHeight = window->getUnclippedPixelRect().getHeight() - formattedArea.getHeight();
337
338        //! Get the formatted line count - using the formatting area obtained above.
339        const float lines = (float)(window->getFont()->getFormattedLineCount(window->getText(), formattedArea, CEGUI::WordWrapLeftAligned));
340
341        //! Calculate pixel height of window, which is the number of formatted lines multiplied by the spacing of the font, plus the pixel height of the frame.
342        const float height = lines * window->getFont()->getLineSpacing() + frameHeight;
343
344        //! Set the height to the window.
345        window->setHeight(CEGUI::UDim(0, height));
346
347        //Debug
348        const CEGUI::Rect newArea = getStaticTextArea(window);
349
350        return static_cast<int>(height);
351    }
352
353    /**
354    @brief
355        Update the position list item.
356    */
357    void QuestGUINode::updatePosition(void)
358    {
359        this->window_->setPosition(CEGUI::UVector2(CEGUI::UDim(0, (float)(QuestGUINode::INDENT_WIDTH*this->depth_)),CEGUI::UDim(0, (float)(QuestGUINode::BUTTON_HEIGHT*this->index_))));
360        this->window_->setSize(CEGUI::UVector2(CEGUI::UDim(1, (float)(-QuestGUINode::INDENT_WIDTH*this->depth_-QuestGUINode::SCROLLBAR_WIDTH)),CEGUI::UDim(0, (float)QuestGUINode::BUTTON_HEIGHT)));
361    }
362
363    /**
364    @brief
365        Helper method to create the CEGUI Window the node.
366    */
367    void QuestGUINode::createWindow(void)
368    {
369        Quest* quest = dynamic_cast<Quest*>(this->item_);
370
371        this->window_ = this->gui_->getWindow();
372        std::ostringstream stream;
373        stream << "QuestGUI/Quests/";
374        if(quest == NULL)
375        {
376            stream << this->parent_->index_ << "/Hints/";
377        }
378        stream << this->index_;
379
380        this->window_->rename(stream.str());
381        this->window_->setText(this->item_->getDescription()->getTitle());
382
383        this->parent_->subNodes_.push_back(this);
384
385        if(dynamic_cast<Quest*>(this->item_) != NULL)
386        {
387            this->gui_->getRootWindow()->addChildWindow(this->window_);
388            this->updatePosition();
389        }
390        else
391        {
392            this->window_->setDestroyedByParent(false);
393        }
394
395        this->window_->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&QuestGUINode::openDetails, this));
396    }
397
398}
399
Note: See TracBrowser for help on using the repository browser.