Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 7401 was 7401, checked in by landauf, 14 years ago

merged doc branch back to trunk

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