Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/core/command/ConsoleCommand.cc @ 7861

Last change on this file since 7861 was 7861, checked in by landauf, 13 years ago

added function to KeyBinder which allows to change the keybind mode (OnPress, OnRelease, OnHold) of a command which is bound to a key.
enhanced ConsoleCommand (+Manipulator) to use this feature.

input system experts, please review :D

  • Property svn:eol-style set to native
File size: 27.4 KB
RevLine 
[1505]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 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
[7401]29/**
30    @file
31    @brief Implementation of the ConsoleCommand class.
32*/
33
[1505]34#include "ConsoleCommand.h"
35
[7214]36#include "util/Convert.h"
[7228]37#include "util/StringUtils.h"
[7203]38#include "core/Language.h"
[7222]39#include "core/GameMode.h"
[7861]40#include "core/input/KeyBinder.h"
41#include "core/input/KeyBinderManager.h"
[7179]42
43namespace orxonox
44{
[7401]45    /**
46        @brief Constructor: Initializes all values and registers the command.
47        @param group The group of the command
48        @param name The name of the command
49        @param executor The executor of the command
50        @param bInitialized If true, the executor is used for both, the definition of the function-header AND to executute the command. If false, the command is inactive and needs to be assigned a function before it can be used.
51    */
[7236]52    ConsoleCommand::ConsoleCommand(const std::string& group, const std::string& name, const ExecutorPtr& executor, bool bInitialized)
[7179]53    {
[7185]54        this->bActive_ = true;
[7215]55        this->bHidden_ = false;
56        this->accessLevel_ = AccessLevel::All;
57
[7214]58        this->baseName_ = name;
[7267]59        this->baseFunctor_ = executor->getFunctor();
[7214]60
[7401]61        for (size_t i = 0; i < MAX_FUNCTOR_ARGUMENTS; ++i)
62            this->argumentCompleter_[i] = 0;
[7215]63
64        this->keybindMode_ = KeybindMode::OnPress;
65        this->inputConfiguredParam_ = -1;
66
[7214]67        if (bInitialized)
68            this->executor_ = executor;
69
[7236]70        ConsoleCommand::registerCommand(group, name, this);
[7179]71    }
72
[7401]73    /**
74        @brief Destructor: Unregisters the command.
75    */
[7236]76    ConsoleCommand::~ConsoleCommand()
[7214]77    {
[7236]78        ConsoleCommand::unregisterCommand(this);
[7214]79    }
80
[7401]81    /**
82        @brief Registers the command with the same name, but without group, as shortcut.
83    */
[7236]84    ConsoleCommand& ConsoleCommand::addShortcut()
[7179]85    {
[7236]86        ConsoleCommand::registerCommand("", this->baseName_, this);
[7179]87        return *this;
88    }
89
[7401]90    /**
91        @brief Registers the command with an alias as shortcut.
92    */
[7236]93    ConsoleCommand& ConsoleCommand::addShortcut(const std::string&  name)
[7179]94    {
[7236]95        ConsoleCommand::registerCommand("", name, this);
[7179]96        return *this;
97    }
98
[7401]99    /**
100        @brief Registers the command in a different group but with the same name.
101    */
[7236]102    ConsoleCommand& ConsoleCommand::addGroup(const std::string& group)
[7179]103    {
[7236]104        ConsoleCommand::registerCommand(group, this->baseName_, this);
[7179]105        return *this;
106    }
107
[7401]108    /**
109        @brief Registers an alias of the command in a different group with a different name.
110    */
[7236]111    ConsoleCommand& ConsoleCommand::addGroup(const std::string& group, const std::string&  name)
[7179]112    {
[7236]113        ConsoleCommand::registerCommand(group, name, this);
[7179]114        return *this;
115    }
116
[7401]117    /**
118        @brief Returns true if the command can be executed right now.
119
120        This returns only true, if the following conditions are met:
121         - The command is active
122         - The command has an executor
123         - The executor has a functor
124         - The functor is static or has an object
125    */
[7236]126    bool ConsoleCommand::isActive() const
[7179]127    {
[7218]128        return (this->bActive_ && this->executor_ && this->executor_->getFunctor() && (this->executor_->getFunctor()->getType() == Functor::Type::Static || this->executor_->getFunctor()->getRawObjectPointer()));
[7214]129    }
130
[7401]131    /**
132        @brief Returns true if the current state of the game matches the required access level.
133    */
[7236]134    bool ConsoleCommand::hasAccess() const
[7222]135    {
136        switch (this->accessLevel_)
137        {
138            case AccessLevel::All:        return true;
139            case AccessLevel::Standalone: return GameMode::isStandalone();
140            case AccessLevel::Master:     return GameMode::isMaster();
[7401]141            case AccessLevel::Server:     return GameMode::isServer();
[7222]142            case AccessLevel::Client:     return GameMode::isClient();
[7401]143            case AccessLevel::Online:     return (GameMode::isServer() || GameMode::isClient());
[7222]144            case AccessLevel::Offline:    return GameMode::isStandalone();
145            case AccessLevel::None:       return false;
146            default:                      return false;
147        }
148    }
149
[7401]150    /**
151        @brief Returns true if the headers of the given functor match the declaration of this command.
152    */
[7236]153    bool ConsoleCommand::headersMatch(const FunctorPtr& functor)
[7214]154    {
[7401]155        // get the minimum of the number of parameters of both commands
[7267]156        unsigned int minparams = std::min(this->baseFunctor_->getParamCount(), functor->getParamCount());
[7214]157
[7401]158        // if the reduced headers don't match -> return false
[7267]159        if (this->baseFunctor_->getHeaderIdentifier(minparams) != functor->getHeaderIdentifier(minparams))
[7214]160            return false;
[7401]161        // if the reduced headers match and the new functor has less or equal parameters -> return true
[7267]162        else if (functor->getParamCount() <= this->baseFunctor_->getParamCount())
[7214]163            return true;
[7401]164        // the headers match but the new functor has more arguments and there is no executor with default-values -> return false
[7214]165        else if (!this->executor_)
166            return false;
[7401]167        // the headers match but the new functor has more arguments, check if the executor has enough default-values
[7214]168        else
[7179]169        {
[7267]170            for (unsigned int i = this->baseFunctor_->getParamCount(); i < functor->getParamCount(); ++i)
171            {
[7214]172                if (!this->executor_->defaultValueSet(i))
[7267]173                {
174                    COUT(2) << "Default value " << i << " is missing" << std::endl;
[7214]175                    return false;
[7267]176                }
177            }
[7214]178
[7185]179            return true;
[7179]180        }
[7214]181    }
[7185]182
[7401]183    /**
184        @brief Returns true if the headers of the given executor match the declaration of this command.
185    */
[7236]186    bool ConsoleCommand::headersMatch(const ExecutorPtr& executor)
[7214]187    {
[7401]188        // get the minimum of the number of parameters of both commands
[7267]189        unsigned int minparams = std::min(this->baseFunctor_->getParamCount(), executor->getParamCount());
[7214]190
[7401]191        // if the reduced headers don't match -> return false
[7267]192        if (this->baseFunctor_->getHeaderIdentifier(minparams) != executor->getFunctor()->getHeaderIdentifier(minparams))
[7214]193            return false;
[7401]194        // if the reduced headers match and the new functor has less or equal parameters -> return true
[7267]195        else if (executor->getParamCount() <= this->baseFunctor_->getParamCount())
[7214]196            return true;
[7401]197        // the headers match but the new functor has more arguments, check if the new executor has enough default-values
[7214]198        else
[7179]199        {
[7267]200            for (unsigned int i = this->baseFunctor_->getParamCount(); i < executor->getParamCount(); ++i)
201            {
[7214]202                if (!executor->defaultValueSet(i))
[7267]203                {
204                    COUT(2) << "Default value " << i << " is missing" << std::endl;
[7214]205                    return false;
[7267]206                }
207            }
[7214]208
209            return true;
210        }
211    }
212
[7401]213    /**
214        @brief Changes the executor.
215        @param executor The new executor
216        @param bForce If true, the executor is always assigned, even if the headers don't match
217        @return Returns true if the assignment was successful
218    */
[7236]219    bool ConsoleCommand::setFunction(const ExecutorPtr& executor, bool bForce)
[7214]220    {
[7401]221        // assign the executor if a) it's a null-pointer, b) its functor is a null-pointer, c) it's forced, d) the headers match
[7214]222        if (!executor || !executor->getFunctor() || bForce || this->headersMatch(executor))
223        {
[7401]224            // assign the executor and clear the object stack (because it's also a new function)
[7214]225            this->executor_ = executor;
[7272]226            this->objectStack_.clear();
[7214]227            return true;
228        }
229        else
230        {
231            COUT(1) << "Error: Couldn't assign new executor to console command \"" << this->baseName_ << "\", headers don't match." << std::endl;
[7185]232            return false;
[7179]233        }
[7214]234    }
[7185]235
[7401]236    /**
237        @brief Changes the functor of the current executor.
238        @param functor The new functor
239        @param bForce If true, the functor is always assigned, even if the headers don't match
240        @return Returns true if the assignment was successful
241    */
[7236]242    bool ConsoleCommand::setFunction(const FunctorPtr& functor, bool bForce)
[7214]243    {
[7401]244        // assign the functor if a) it's a null-pointer, b) it's forced, c) the headers match
[7214]245        if (!functor || bForce || this->headersMatch(functor))
246        {
[7401]247            // assign the functor (create a new executor if necessary) and clear the object stack
[7214]248            if (this->executor_)
249                this->executor_->setFunctor(functor);
[7218]250            else if (functor)
[7214]251                this->executor_ = createExecutor(functor);
[7272]252            this->objectStack_.clear();
[7214]253
254            return true;
255        }
256        else
257        {
258            COUT(1) << "Error: Couldn't assign new functor to console command \"" << this->baseName_ << "\", headers don't match." << std::endl;
259            return false;
260        }
[7179]261    }
262
[7401]263    /**
264        @brief Pushes a new executor to the command-stack.
265        @param executor The new executor
266        @param bForce If true, the executor is always assigned, even if the headers don't match
267    */
[7236]268    void ConsoleCommand::pushFunction(const ExecutorPtr& executor, bool bForce)
[7179]269    {
[7401]270        // prepare the old function to be put on the stack
[7214]271        Command command;
[7270]272        command.executor_ = this->executor_;
[7214]273        if (command.executor_)
[7270]274            command.functor_ = this->executor_->getFunctor();
[7272]275        command.objectStack_ = this->objectStack_;
[7185]276
[7401]277        // check if the new executor can be assigned and push the old function to the stack
[7214]278        if (this->setFunction(executor, bForce))
279            this->commandStack_.push(command);
[7179]280    }
281
[7401]282    /**
283        @brief Pushes a new functor to the command-stack.
284        @param functor The new functor
285        @param bForce If true, the functor is always assigned, even if the headers don't match
286    */
[7236]287    void ConsoleCommand::pushFunction(const FunctorPtr& functor, bool bForce)
[7179]288    {
[7401]289        // prepare the old function to be put on the stack
[7214]290        Command command;
[7270]291        command.executor_ = this->executor_;
[7214]292        if (command.executor_)
[7270]293            command.functor_ = this->executor_->getFunctor();
[7272]294        command.objectStack_ = this->objectStack_;
[7214]295
[7401]296        // check if the new functor can be assigned and push the old function to the stack
[7214]297        if (this->setFunction(functor, bForce))
298            this->commandStack_.push(command);
[7185]299    }
[7179]300
[7401]301    /**
302        @brief Pushes a copy of the current executor and functor on the stack.
303    */
[7236]304    void ConsoleCommand::pushFunction()
[7185]305    {
[7214]306        if (this->executor_)
307            this->pushFunction(new Executor(*this->executor_.get()));
308        else
309            COUT(1) << "Error: Couldn't push copy of executor in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
[7179]310    }
311
[7401]312    /**
313        @brief Removes the current function from the stack and restores the old state.
314    */
[7236]315    void ConsoleCommand::popFunction()
[7179]316    {
[7214]317        Command command;
[7401]318
319        // check if there's a function on the stack
[7214]320        if (!this->commandStack_.empty())
[7179]321        {
[7401]322            // yes it is - assign it to command and remove it from the stack
[7214]323            command = this->commandStack_.top();
324            this->commandStack_.pop();
[7179]325        }
[7214]326
[7401]327        // restore the old executor (and also restore its functor in case this was changed in the meantime)
[7214]328        this->executor_ = command.executor_;
329        if (command.executor_)
330            this->executor_->setFunctor(command.functor_);
[7272]331        this->objectStack_ = command.objectStack_;
[7179]332    }
333
[7401]334    /**
335        @brief Sets the functor to NULL (which also deactivates the command).
336    */
[7236]337    void ConsoleCommand::resetFunction()
[7218]338    {
339        if (this->executor_)
340            this->executor_->setFunctor(0);
[7272]341        this->objectStack_.clear();
[7218]342    }
343
[7401]344    /**
345        @brief Returns the current executor which can be used to execute the command.
346    */
[7236]347    const ExecutorPtr& ConsoleCommand::getExecutor() const
[7179]348    {
[7214]349        return this->executor_;
[7179]350    }
351
[7401]352    /**
353        @brief Changes the current object that is used to execute member-functions.
354        @return Returns true if the object was successfully changed
355    */
[7236]356    bool ConsoleCommand::setObject(void* object)
[7214]357    {
[7401]358        // check if there's an executor
[7214]359        if (this->executor_)
[7185]360        {
[7401]361            // check if there's a functor
[7214]362            if (this->executor_->getFunctor())
363            {
[7401]364                // change the object
[7214]365                this->executor_->getFunctor()->setRawObjectPointer(object);
366                return true;
367            }
368            else if (object)
369                COUT(1) << "Error: Can't assign object to console command \"" << this->baseName_ << "\", no functor set." << std::endl;
[7185]370        }
[7214]371        else if (object)
372            COUT(1) << "Error: Can't assign object to console command \"" << this->baseName_ << "\", no executor set." << std::endl;
373
374        return false;
[7179]375    }
376
[7401]377    /**
378        @brief Push a new object to the object-stack.
379    */
[7236]380    void ConsoleCommand::pushObject(void* object)
[7214]381    {
382        void* oldobject = this->getObject();
383        if (this->setObject(object))
[7272]384            this->objectStack_.push_back(oldobject);
[7214]385    }
386
[7401]387    /**
388        @brief Removes the current object from the stack an restores the old object.
389    */
[7236]390    void ConsoleCommand::popObject()
[7185]391    {
392        void* newobject = 0;
393        if (!this->objectStack_.empty())
394        {
[7272]395            newobject = this->objectStack_.back();
396            this->objectStack_.pop_back();
[7185]397        }
398        this->setObject(newobject);
399    }
400
[7401]401    /**
402        @brief Returns the current object pointer that is used to execute member-functions.
403    */
[7236]404    void* ConsoleCommand::getObject() const
[7185]405    {
[7214]406        if (this->executor_ && this->executor_->getFunctor())
407            return this->executor_->getFunctor()->getRawObjectPointer();
[7185]408        else
409            return 0;
410    }
411
[7401]412    /**
413        @brief Changes the default values of the current executor.
414    */
415    ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& arg1)
[7215]416    {
417        if (this->executor_)
[7401]418            this->executor_->setDefaultValues(arg1);
[7215]419        else
420            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
421
422        return *this;
423    }
424
[7401]425    /**
426        @brief Changes the default values of the current executor.
427    */
428    ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& arg1, const MultiType& arg2)
[7215]429    {
430        if (this->executor_)
[7401]431            this->executor_->setDefaultValues(arg1, arg2);
[7215]432        else
433            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
434
435        return *this;
436    }
437
[7401]438    /**
439        @brief Changes the default values of the current executor.
440    */
441    ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3)
[7215]442    {
443        if (this->executor_)
[7401]444            this->executor_->setDefaultValues(arg1, arg2, arg3);
[7215]445        else
446            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
447
448        return *this;
449    }
450
[7401]451    /**
452        @brief Changes the default values of the current executor.
453    */
454    ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4)
[7215]455    {
456        if (this->executor_)
[7401]457            this->executor_->setDefaultValues(arg1, arg2, arg3, arg4);
[7215]458        else
459            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
460
461        return *this;
462    }
463
[7401]464    /**
465        @brief Changes the default values of the current executor.
466    */
467    ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4, const MultiType& arg5)
[7215]468    {
469        if (this->executor_)
[7401]470            this->executor_->setDefaultValues(arg1, arg2, arg3, arg4, arg5);
[7215]471        else
472            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
473
474        return *this;
475    }
476
[7401]477    /**
478        @brief Changes the default value of the argument with given index of the current executor.
479        @param index The index of the argument (the first argument has index 0)
480        @param arg The new default value
481    */
482    ConsoleCommand& ConsoleCommand::defaultValue(unsigned int index, const MultiType& arg)
[7215]483    {
484        if (this->executor_)
[7401]485            this->executor_->setDefaultValue(index, arg);
[7215]486        else
487            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
488
489        return *this;
490    }
491
[7401]492    /**
493        @brief Changes the argument completer for the given argument.
494        @param index The index of the argument (the first argument has index 0)
495        @param completer The new argument completer
496    */
497    ConsoleCommand& ConsoleCommand::argumentCompleter(unsigned int index, ArgumentCompleter* completer)
[7215]498    {
[7401]499        if (index < 5)
500            this->argumentCompleter_[index] = completer;
[7215]501        else
[7401]502            COUT(2) << "Warning: Couldn't add autocompletion-function for index " << index << " in console command \"" << this->baseName_ << "\": index out of bound." << std::endl;
[7215]503
504        return *this;
505    }
506
[7401]507    /**
508        @brief Returns the argument completer for the argument with given index.
509    */
510    ArgumentCompleter* ConsoleCommand::getArgumentCompleter(unsigned int index) const
[7215]511    {
[7401]512        if (index < 5)
513            return this->argumentCompleter_[index];
[7215]514        else
515            return 0;
516    }
517
[7401]518    /**
519        @brief Sets the description of this command.
520    */
[7236]521    ConsoleCommand& ConsoleCommand::description(const std::string& description)
[7215]522    {
523        this->description_ = std::string("ConsoleCommandDescription::" + this->baseName_ + "::function");
524        AddLanguageEntry(this->description_, description);
525        return *this;
526    }
527
[7401]528    /**
529        @brief Returns the description of this command.
530    */
[7236]531    const std::string& ConsoleCommand::getDescription() const
[7215]532    {
533        return GetLocalisation_noerror(this->description_);
534    }
535
[7401]536    /**
537        @brief Sets the description for an argument with given index.
538    */
539    ConsoleCommand& ConsoleCommand::descriptionParam(unsigned int index, const std::string& description)
[7215]540    {
[7401]541        if (index < MAX_FUNCTOR_ARGUMENTS)
[7215]542        {
[7401]543            this->descriptionParam_[index] = std::string("ConsoleCommandDescription::" + this->baseName_ + "::param" + multi_cast<std::string>(index));
544            AddLanguageEntry(this->descriptionParam_[index], description);
[7215]545        }
546        return *this;
547    }
548
[7401]549    /**
550        @brief Returns the description for the argument with given index.
551    */
552    const std::string& ConsoleCommand::getDescriptionParam(unsigned int index) const
[7215]553    {
[7401]554        if (index < MAX_FUNCTOR_ARGUMENTS)
555            return GetLocalisation_noerror(this->descriptionParam_[index]);
[7215]556
557        return this->descriptionParam_[0];
558    }
559
[7401]560    /**
561        @brief Sets the description for the return-value.
562    */
[7236]563    ConsoleCommand& ConsoleCommand::descriptionReturnvalue(const std::string& description)
[7215]564    {
565        this->descriptionReturnvalue_ = std::string("ConsoleCommandDescription::" + this->baseName_ + "::returnvalue");
566        AddLanguageEntry(this->descriptionReturnvalue_, description);
567        return *this;
568    }
569
[7401]570    /**
571        @brief Returns the description for the return-value.
572    */
573    const std::string& ConsoleCommand::getDescriptionReturnvalue(int index) const
[7215]574    {
575        return GetLocalisation_noerror(this->descriptionReturnvalue_);
576    }
577
[7401]578    /**
[7861]579        @brief Changes the keybind mode.
580    */
581    ConsoleCommand& ConsoleCommand::changeKeybindMode(KeybindMode::Value mode)
582    {
583        KeyBinderManager::getInstance().getCurrent()->changeMode(this, mode);
584
585        this->keybindMode(mode);
586        return *this;
587    }
588
589    /**
[7401]590        @brief Returns the command with given group an name.
591        @param group The group of the requested command
592        @param name The group of the requested command
593        @param bPrintError If true, an error is printed if the command doesn't exist
594    */
[7282]595    /* static */ const ConsoleCommand* ConsoleCommand::getCommand(const std::string& group, const std::string& name, bool bPrintError)
[7179]596    {
[7401]597        // find the group
[7236]598        std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommandMap().find(group);
599        if (it_group != ConsoleCommand::getCommandMap().end())
[7179]600        {
[7401]601            // find the name
[7236]602            std::map<std::string, ConsoleCommand*>::const_iterator it_name = it_group->second.find(name);
[7179]603            if (it_name != it_group->second.end())
604            {
[7401]605                // return the pointer
[7179]606                return it_name->second;
607            }
608        }
609        if (bPrintError)
610        {
611            if (group == "")
[7198]612                COUT(1) << "Error: Couldn't find console command with shortcut \"" << name << "\"" << std::endl;
[7179]613            else
[7198]614                COUT(1) << "Error: Couldn't find console command with group \"" << group << "\" and name \"" << name << "\"" << std::endl;
[7179]615        }
616        return 0;
617    }
618
[7401]619    /**
620        @brief Returns the command with given group an name in lowercase.
621        @param group The group of the requested command in lowercase
622        @param name The group of the requested command in lowercase
623        @param bPrintError If true, an error is printed if the command doesn't exist
624    */
[7282]625    /* static */ const ConsoleCommand* ConsoleCommand::getCommandLC(const std::string& group, const std::string& name, bool bPrintError)
[7228]626    {
627        std::string groupLC = getLowercase(group);
628        std::string nameLC = getLowercase(name);
629
[7401]630        // find the group
[7236]631        std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommandMapLC().find(groupLC);
632        if (it_group != ConsoleCommand::getCommandMapLC().end())
[7228]633        {
[7401]634            // find the name
[7236]635            std::map<std::string, ConsoleCommand*>::const_iterator it_name = it_group->second.find(nameLC);
[7228]636            if (it_name != it_group->second.end())
637            {
[7401]638                // return the pointer
[7228]639                return it_name->second;
640            }
641        }
642        if (bPrintError)
643        {
644            if (group == "")
645                COUT(1) << "Error: Couldn't find console command with shortcut \"" << name << "\"" << std::endl;
646            else
647                COUT(1) << "Error: Couldn't find console command with group \"" << group << "\" and name \"" << name << "\"" << std::endl;
648        }
649        return 0;
650    }
651
[7401]652    /**
653        @brief Returns the static map that stores all console commands.
654    */
[7236]655    /* static */ std::map<std::string, std::map<std::string, ConsoleCommand*> >& ConsoleCommand::getCommandMap()
[7179]656    {
[7236]657        static std::map<std::string, std::map<std::string, ConsoleCommand*> > commandMap;
[7179]658        return commandMap;
659    }
660
[7401]661    /**
662        @brief Returns the static map that stores all console commands in lowercase.
663    */
[7236]664    /* static */ std::map<std::string, std::map<std::string, ConsoleCommand*> >& ConsoleCommand::getCommandMapLC()
[7228]665    {
[7236]666        static std::map<std::string, std::map<std::string, ConsoleCommand*> > commandMapLC;
[7228]667        return commandMapLC;
668    }
669
[7401]670    /**
671        @brief Registers a new command with given group an name by adding it to the command map.
672    */
[7236]673    /* static */ void ConsoleCommand::registerCommand(const std::string& group, const std::string& name, ConsoleCommand* command)
[7179]674    {
675        if (name == "")
676            return;
677
[7401]678        // check if a command with this name already exists
[7236]679        if (ConsoleCommand::getCommand(group, name) != 0)
[7179]680        {
681            if (group == "")
[7214]682                COUT(2) << "Warning: A console command with shortcut \"" << name << "\" already exists." << std::endl;
[7179]683            else
[7214]684                COUT(2) << "Warning: A console command with name \"" << name << "\" already exists in group \"" << group << "\"." << std::endl;
[7179]685        }
686        else
687        {
[7401]688            // add the command to the map
[7236]689            ConsoleCommand::getCommandMap()[group][name] = command;
690            ConsoleCommand::getCommandMapLC()[getLowercase(group)][getLowercase(name)] = command;
[7179]691        }
692    }
[7214]693
[7401]694    /**
695        @brief Removes the command from the command map.
696    */
[7236]697    /* static */ void ConsoleCommand::unregisterCommand(ConsoleCommand* command)
[7214]698    {
[7401]699        // iterate through all groups
[7236]700        for (std::map<std::string, std::map<std::string, ConsoleCommand*> >::iterator it_group = ConsoleCommand::getCommandMap().begin(); it_group != ConsoleCommand::getCommandMap().end(); )
[7214]701        {
[7401]702            // iterate through all commands of each group
[7236]703            for (std::map<std::string, ConsoleCommand*>::iterator it_name = it_group->second.begin(); it_name != it_group->second.end(); )
[7214]704            {
[7401]705                // erase the command
[7214]706                if (it_name->second == command)
707                    it_group->second.erase(it_name++);
708                else
709                    ++it_name;
710            }
711
[7401]712            // erase the group if it is empty now
[7214]713            if (it_group->second.empty())
[7236]714                ConsoleCommand::getCommandMap().erase(it_group++);
[7214]715            else
716                ++it_group;
717        }
[7228]718
[7401]719        // now the same for the lowercase-map:
720
721        // iterate through all groups
[7236]722        for (std::map<std::string, std::map<std::string, ConsoleCommand*> >::iterator it_group = ConsoleCommand::getCommandMapLC().begin(); it_group != ConsoleCommand::getCommandMapLC().end(); )
[7228]723        {
[7401]724            // iterate through all commands of each group
[7236]725            for (std::map<std::string, ConsoleCommand*>::iterator it_name = it_group->second.begin(); it_name != it_group->second.end(); )
[7228]726            {
[7401]727                // erase the command
[7228]728                if (it_name->second == command)
729                    it_group->second.erase(it_name++);
730                else
731                    ++it_name;
732            }
733
[7401]734            // erase the group if it is empty now
[7228]735            if (it_group->second.empty())
[7236]736                ConsoleCommand::getCommandMapLC().erase(it_group++);
[7228]737            else
738                ++it_group;
739        }
[7214]740    }
[7216]741
[7401]742    /**
743        @brief Deletes all commands
744    */
[7236]745    /* static */ void ConsoleCommand::destroyAll()
[7216]746    {
[7401]747        // delete entries until the map is empty
[7236]748        while (!ConsoleCommand::getCommandMap().empty() && !ConsoleCommand::getCommandMap().begin()->second.empty())
749            delete ConsoleCommand::getCommandMap().begin()->second.begin()->second;
[7216]750    }
[7179]751}
Note: See TracBrowser for help on using the repository browser.