/* * ORXONOX - the hottest 3D action shooter ever to exist * > www.orxonox.net < * * * License notice: * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Author: * Damian 'Mozork' Frick * Co-authors: * ... * */ #include "QuestGUI.h" #include #include #include #include "core/CoreIncludes.h" #include "Quest.h" #include "QuestHint.h" #include "QuestItem.h" #include "QuestGUINode.h" #include "QuestManager.h" namespace orxonox { /** @brief Constructor. Registers and initializes the object. @param The player the GUI is for. */ QuestGUI::QuestGUI(PlayerInfo* player) { RegisterRootObject(QuestGUI); this->player_ = player; this->windowManager_ = CEGUI::WindowManager::getSingletonPtr(); //!< Get CEGUI WindowManager. this->rootWindow_ = NULL; this->root_ = new QuestGUINode(); //!< Create empty root node. COUT(3) << "New QuestGUI created." << std::endl; } /** @brief Destructor. */ QuestGUI::~QuestGUI() { COUT(3) << "Destroying QuestGUI..." << std::endl; this->clear(); //!< Clearing the GUI and in the process destroying all QuestGUINodes. //! Destroying the windows in the this->windows_ list. for(std::list::iterator it = this->windows_.begin(); it != this->windows_.end(); it++) { if(*it != NULL) (*it)->destroy(); } this->windows_.clear(); if(this->root_ != NULL) this->root_->destroy(); } /** @brief Get the root CEGUI Window of the GUI. @return Returns the root CEGUI Window of the GUI. */ CEGUI::Window* QuestGUI::getGUI(void) { this->update(); //!< Update the GUI. return this->rootWindow_; } /** @brief Update the GUI. */ void QuestGUI::update(void) { COUT(4) << "Updating QuestGUI..." << std::endl; this->clear(); //!< Clear the GUI. int depth = 0; int index = 0; //! Create root window. this->rootWindow_ = this->windowManager_->createWindow("MenuWidgets/ScrollablePane", "QuestGUI/Quests"); this->rootWindow_->setSize(CEGUI::UVector2(CEGUI::UDim(1, 0),CEGUI::UDim(1, 0))); //! Iterate through all Quests. std::map quests = QuestManager::getInstance().getQuests(); for(std::map::iterator it = quests.begin(); it != quests.end(); it++) { Quest* quest = it->second; if(quest->getParentQuest() == NULL && !quest->isInactive(this->player_)) //!< If the Quest isn't inactive and a root Quest (meaning it has no parent.), create a Node. { index = createNode(this->root_, quest, depth, index); } } COUT(4) << "Updating QuestGUI done." << std::endl; } /** @brief Clear the QuestGUI. */ void QuestGUI::clear(void) { COUT(4) << "Clearing QuestGUI..." << std::endl; //! Clear all nodes. for(std::map::iterator it = this->nodes_.begin(); it != this->nodes_.end(); it++) { QuestGUINode* node = it->second; if(node == NULL) { COUT(1) << "Node is NULL!"; continue; } std::string* str = new std::string(); node->getName(*str); COUT(3) << "Clearing Node '" << *str << "' ..." << std::endl; delete str; node->destroy(); } this->nodes_.clear(); //! Clear root window. if(this->rootWindow_ != NULL) this->rootWindow_->destroy(); COUT(3) << "Clearing QuestGUI done." << std::endl; } /** @brief Get a CEGUI Window to use. Windows that are no longer used are collected with giveWindow, and are given out again with getWindow, so save some time recreating new windows everytime. The retreived window is of type "MenuWidgets/TabButton". @return Returns a CEGUI Window of type "MenuWidgets/TabButton". */ CEGUI::Window* QuestGUI::getWindow(void) { if(!this->windows_.empty()) //!< If there are windows in the list. { CEGUI::Window* window = this->windows_.back(); this->windows_.pop_back(); return window; } //!< Else create a new one. std::ostringstream stream; stream << "QuestGUI/Quests/EmptyWindows/" << this->windows_.size()+1; return this->windowManager_->createWindow("MenuWidgets/TabButton", stream.str()); } /** @brief Return a no longer needed CEGUI Window for reuse. @param window The CEGUI window ot be returned. */ void QuestGUI::giveWindow(CEGUI::Window* window) { if(window == NULL) return; this->windows_.push_back(window); this->rootWindow_->removeChildWindow(window); //!< Remove the window as child of the rootWindow. std::ostringstream stream; stream << "QuestGUI/Quests/EmptyWindows/" << this->windows_.size(); window->rename(stream.str()); } /** @brief Finde the QuestGUINode belonging to the input CEGUI Window. @param window A pointer to a CEGUI Window. @return A pointer to the QuestGUI Node belonging to the input CEGUI Window. */ /*static*/ QuestGUINode* QuestGUI::findNode(CEGUI::Window* window) { for(std::map::iterator it = QuestManager::getInstance().questGUIs_.begin(); it != QuestManager::getInstance().questGUIs_.end(); it++) { QuestGUI* gui = it->second; std::map::iterator node = gui->nodes_.find(window); if(node != gui->nodes_.end()) return node->second; } return NULL; } /** @brief Recursive method to create Nodes for all Quests an Hints the given Quest is a parent to. @param parent Pointer to the parent QuestGUINode. @param item The QuestItem the QuestGUINode is created for. @param depth Parameter to define how much the list item has to be indented. @param index "Counter" for Quests and Hints. @return Returns the index. */ int QuestGUI::createNode(QuestGUINode* parent, QuestItem* item, int depth, int index) { QuestGUINode* node = new QuestGUINode(this, parent, item, depth, index); //!< Create a new QuestGUINode. this->nodes_.insert(std::pair(node->getWindow(),node)); //!< Insert the node and its window in the nodes_ map. index++; //! Check if the QuestItem is a Quest, if not (it's a QuestHint) it just returns. Quest* quest = dynamic_cast(item); if(quest == NULL) return index; //! Iterate through all subQuests. std::list quests = quest->getSubQuestList(); for(std::list::iterator it = quests.begin(); it != quests.end(); it++) { Quest* quest = *it; if(!quest->isInactive(this->player_)) //!< Add node if the subQuest is not inactive. { index = createNode(node, quest, depth+1, index); } } //! Iterate through all hints. std::list hints = quest->getHintsList(); int tempIndex = index; //!< Preserve the index, since for the hints we start anew with index 0. index = 0; for(std::list::iterator it = hints.begin(); it != hints.end(); it++) { QuestHint* hint = *it; if(hint->isActive(this->player_)) //!< Add node if the hint is active. { index = createNode(node, hint, depth+1, index); } } index = tempIndex; //!< Reset the index to the original level. return index; } }