Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/lastmanstanding2/src/libraries/core/command/ConsoleCommand.cc @ 8740

Last change on this file since 8740 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
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 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30    @file
31    @brief Implementation of the ConsoleCommand class.
32*/
33
34#include "ConsoleCommand.h"
35
36#include "util/Convert.h"
37#include "util/StringUtils.h"
38#include "core/Language.h"
39#include "core/GameMode.h"
40
41namespace orxonox
42{
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    */
50    ConsoleCommand::ConsoleCommand(const std::string& group, const std::string& name, const ExecutorPtr& executor, bool bInitialized)
51    {
52        this->bActive_ = true;
53        this->bHidden_ = false;
54        this->accessLevel_ = AccessLevel::All;
55
56        this->baseName_ = name;
57        this->baseFunctor_ = executor->getFunctor();
58
59        for (size_t i = 0; i < MAX_FUNCTOR_ARGUMENTS; ++i)
60            this->argumentCompleter_[i] = 0;
61
62        this->keybindMode_ = KeybindMode::OnPress;
63        this->inputConfiguredParam_ = -1;
64
65        if (bInitialized)
66            this->executor_ = executor;
67
68        ConsoleCommand::registerCommand(group, name, this);
69    }
70
71    /**
72        @brief Destructor: Unregisters the command.
73    */
74    ConsoleCommand::~ConsoleCommand()
75    {
76        ConsoleCommand::unregisterCommand(this);
77    }
78
79    /**
80        @brief Registers the command with the same name, but without group, as shortcut.
81    */
82    ConsoleCommand& ConsoleCommand::addShortcut()
83    {
84        ConsoleCommand::registerCommand("", this->baseName_, this);
85        return *this;
86    }
87
88    /**
89        @brief Registers the command with an alias as shortcut.
90    */
91    ConsoleCommand& ConsoleCommand::addShortcut(const std::string&  name)
92    {
93        ConsoleCommand::registerCommand("", name, this);
94        return *this;
95    }
96
97    /**
98        @brief Registers the command in a different group but with the same name.
99    */
100    ConsoleCommand& ConsoleCommand::addGroup(const std::string& group)
101    {
102        ConsoleCommand::registerCommand(group, this->baseName_, this);
103        return *this;
104    }
105
106    /**
107        @brief Registers an alias of the command in a different group with a different name.
108    */
109    ConsoleCommand& ConsoleCommand::addGroup(const std::string& group, const std::string&  name)
110    {
111        ConsoleCommand::registerCommand(group, name, this);
112        return *this;
113    }
114
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    */
124    bool ConsoleCommand::isActive() const
125    {
126        return (this->bActive_ && this->executor_ && this->executor_->getFunctor() && (this->executor_->getFunctor()->getType() == Functor::Type::Static || this->executor_->getFunctor()->getRawObjectPointer()));
127    }
128
129    /**
130        @brief Returns true if the current state of the game matches the required access level.
131    */
132    bool ConsoleCommand::hasAccess() const
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();
139            case AccessLevel::Server:     return GameMode::isServer();
140            case AccessLevel::Client:     return GameMode::isClient();
141            case AccessLevel::Online:     return (GameMode::isServer() || GameMode::isClient());
142            case AccessLevel::Offline:    return GameMode::isStandalone();
143            case AccessLevel::None:       return false;
144            default:                      return false;
145        }
146    }
147
148    /**
149        @brief Returns true if the headers of the given functor match the declaration of this command.
150    */
151    bool ConsoleCommand::headersMatch(const FunctorPtr& functor)
152    {
153        // get the minimum of the number of parameters of both commands
154        unsigned int minparams = std::min(this->baseFunctor_->getParamCount(), functor->getParamCount());
155
156        // if the reduced headers don't match -> return false
157        if (this->baseFunctor_->getHeaderIdentifier(minparams) != functor->getHeaderIdentifier(minparams))
158            return false;
159        // if the reduced headers match and the new functor has less or equal parameters -> return true
160        else if (functor->getParamCount() <= this->baseFunctor_->getParamCount())
161            return true;
162        // the headers match but the new functor has more arguments and there is no executor with default-values -> return false
163        else if (!this->executor_)
164            return false;
165        // the headers match but the new functor has more arguments, check if the executor has enough default-values
166        else
167        {
168            for (unsigned int i = this->baseFunctor_->getParamCount(); i < functor->getParamCount(); ++i)
169            {
170                if (!this->executor_->defaultValueSet(i))
171                {
172                    COUT(2) << "Default value " << i << " is missing" << std::endl;
173                    return false;
174                }
175            }
176
177            return true;
178        }
179    }
180
181    /**
182        @brief Returns true if the headers of the given executor match the declaration of this command.
183    */
184    bool ConsoleCommand::headersMatch(const ExecutorPtr& executor)
185    {
186        // get the minimum of the number of parameters of both commands
187        unsigned int minparams = std::min(this->baseFunctor_->getParamCount(), executor->getParamCount());
188
189        // if the reduced headers don't match -> return false
190        if (this->baseFunctor_->getHeaderIdentifier(minparams) != executor->getFunctor()->getHeaderIdentifier(minparams))
191            return false;
192        // if the reduced headers match and the new functor has less or equal parameters -> return true
193        else if (executor->getParamCount() <= this->baseFunctor_->getParamCount())
194            return true;
195        // the headers match but the new functor has more arguments, check if the new executor has enough default-values
196        else
197        {
198            for (unsigned int i = this->baseFunctor_->getParamCount(); i < executor->getParamCount(); ++i)
199            {
200                if (!executor->defaultValueSet(i))
201                {
202                    COUT(2) << "Default value " << i << " is missing" << std::endl;
203                    return false;
204                }
205            }
206
207            return true;
208        }
209    }
210
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    */
217    bool ConsoleCommand::setFunction(const ExecutorPtr& executor, bool bForce)
218    {
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
220        if (!executor || !executor->getFunctor() || bForce || this->headersMatch(executor))
221        {
222            // assign the executor and clear the object stack (because it's also a new function)
223            this->executor_ = executor;
224            this->objectStack_.clear();
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;
230            return false;
231        }
232    }
233
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    */
240    bool ConsoleCommand::setFunction(const FunctorPtr& functor, bool bForce)
241    {
242        // assign the functor if a) it's a null-pointer, b) it's forced, c) the headers match
243        if (!functor || bForce || this->headersMatch(functor))
244        {
245            // assign the functor (create a new executor if necessary) and clear the object stack
246            if (this->executor_)
247                this->executor_->setFunctor(functor);
248            else if (functor)
249                this->executor_ = createExecutor(functor);
250            this->objectStack_.clear();
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        }
259    }
260
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    */
266    void ConsoleCommand::pushFunction(const ExecutorPtr& executor, bool bForce)
267    {
268        // prepare the old function to be put on the stack
269        Command command;
270        command.executor_ = this->executor_;
271        if (command.executor_)
272            command.functor_ = this->executor_->getFunctor();
273        command.objectStack_ = this->objectStack_;
274
275        // check if the new executor can be assigned and push the old function to the stack
276        if (this->setFunction(executor, bForce))
277            this->commandStack_.push(command);
278    }
279
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    */
285    void ConsoleCommand::pushFunction(const FunctorPtr& functor, bool bForce)
286    {
287        // prepare the old function to be put on the stack
288        Command command;
289        command.executor_ = this->executor_;
290        if (command.executor_)
291            command.functor_ = this->executor_->getFunctor();
292        command.objectStack_ = this->objectStack_;
293
294        // check if the new functor can be assigned and push the old function to the stack
295        if (this->setFunction(functor, bForce))
296            this->commandStack_.push(command);
297    }
298
299    /**
300        @brief Pushes a copy of the current executor and functor on the stack.
301    */
302    void ConsoleCommand::pushFunction()
303    {
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;
308    }
309
310    /**
311        @brief Removes the current function from the stack and restores the old state.
312    */
313    void ConsoleCommand::popFunction()
314    {
315        Command command;
316
317        // check if there's a function on the stack
318        if (!this->commandStack_.empty())
319        {
320            // yes it is - assign it to command and remove it from the stack
321            command = this->commandStack_.top();
322            this->commandStack_.pop();
323        }
324
325        // restore the old executor (and also restore its functor in case this was changed in the meantime)
326        this->executor_ = command.executor_;
327        if (command.executor_)
328            this->executor_->setFunctor(command.functor_);
329        this->objectStack_ = command.objectStack_;
330    }
331
332    /**
333        @brief Sets the functor to NULL (which also deactivates the command).
334    */
335    void ConsoleCommand::resetFunction()
336    {
337        if (this->executor_)
338            this->executor_->setFunctor(0);
339        this->objectStack_.clear();
340    }
341
342    /**
343        @brief Returns the current executor which can be used to execute the command.
344    */
345    const ExecutorPtr& ConsoleCommand::getExecutor() const
346    {
347        return this->executor_;
348    }
349
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    */
354    bool ConsoleCommand::setObject(void* object)
355    {
356        // check if there's an executor
357        if (this->executor_)
358        {
359            // check if there's a functor
360            if (this->executor_->getFunctor())
361            {
362                // change the object
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;
368        }
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;
373    }
374
375    /**
376        @brief Push a new object to the object-stack.
377    */
378    void ConsoleCommand::pushObject(void* object)
379    {
380        void* oldobject = this->getObject();
381        if (this->setObject(object))
382            this->objectStack_.push_back(oldobject);
383    }
384
385    /**
386        @brief Removes the current object from the stack an restores the old object.
387    */
388    void ConsoleCommand::popObject()
389    {
390        void* newobject = 0;
391        if (!this->objectStack_.empty())
392        {
393            newobject = this->objectStack_.back();
394            this->objectStack_.pop_back();
395        }
396        this->setObject(newobject);
397    }
398
399    /**
400        @brief Returns the current object pointer that is used to execute member-functions.
401    */
402    void* ConsoleCommand::getObject() const
403    {
404        if (this->executor_ && this->executor_->getFunctor())
405            return this->executor_->getFunctor()->getRawObjectPointer();
406        else
407            return 0;
408    }
409
410    /**
411        @brief Changes the default values of the current executor.
412    */
413    ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& arg1)
414    {
415        if (this->executor_)
416            this->executor_->setDefaultValues(arg1);
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
423    /**
424        @brief Changes the default values of the current executor.
425    */
426    ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& arg1, const MultiType& arg2)
427    {
428        if (this->executor_)
429            this->executor_->setDefaultValues(arg1, arg2);
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
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)
440    {
441        if (this->executor_)
442            this->executor_->setDefaultValues(arg1, arg2, arg3);
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
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)
453    {
454        if (this->executor_)
455            this->executor_->setDefaultValues(arg1, arg2, arg3, arg4);
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
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)
466    {
467        if (this->executor_)
468            this->executor_->setDefaultValues(arg1, arg2, arg3, arg4, arg5);
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
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)
481    {
482        if (this->executor_)
483            this->executor_->setDefaultValue(index, arg);
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
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)
496    {
497        if (index < 5)
498            this->argumentCompleter_[index] = completer;
499        else
500            COUT(2) << "Warning: Couldn't add autocompletion-function for index " << index << " in console command \"" << this->baseName_ << "\": index out of bound." << std::endl;
501
502        return *this;
503    }
504
505    /**
506        @brief Returns the argument completer for the argument with given index.
507    */
508    ArgumentCompleter* ConsoleCommand::getArgumentCompleter(unsigned int index) const
509    {
510        if (index < 5)
511            return this->argumentCompleter_[index];
512        else
513            return 0;
514    }
515
516    /**
517        @brief Sets the description of this command.
518    */
519    ConsoleCommand& ConsoleCommand::description(const std::string& description)
520    {
521        this->description_ = std::string("ConsoleCommandDescription::" + this->baseName_ + "::function");
522        AddLanguageEntry(this->description_, description);
523        return *this;
524    }
525
526    /**
527        @brief Returns the description of this command.
528    */
529    const std::string& ConsoleCommand::getDescription() const
530    {
531        return GetLocalisation_noerror(this->description_);
532    }
533
534    /**
535        @brief Sets the description for an argument with given index.
536    */
537    ConsoleCommand& ConsoleCommand::descriptionParam(unsigned int index, const std::string& description)
538    {
539        if (index < MAX_FUNCTOR_ARGUMENTS)
540        {
541            this->descriptionParam_[index] = std::string("ConsoleCommandDescription::" + this->baseName_ + "::param" + multi_cast<std::string>(index));
542            AddLanguageEntry(this->descriptionParam_[index], description);
543        }
544        return *this;
545    }
546
547    /**
548        @brief Returns the description for the argument with given index.
549    */
550    const std::string& ConsoleCommand::getDescriptionParam(unsigned int index) const
551    {
552        if (index < MAX_FUNCTOR_ARGUMENTS)
553            return GetLocalisation_noerror(this->descriptionParam_[index]);
554
555        return this->descriptionParam_[0];
556    }
557
558    /**
559        @brief Sets the description for the return-value.
560    */
561    ConsoleCommand& ConsoleCommand::descriptionReturnvalue(const std::string& description)
562    {
563        this->descriptionReturnvalue_ = std::string("ConsoleCommandDescription::" + this->baseName_ + "::returnvalue");
564        AddLanguageEntry(this->descriptionReturnvalue_, description);
565        return *this;
566    }
567
568    /**
569        @brief Returns the description for the return-value.
570    */
571    const std::string& ConsoleCommand::getDescriptionReturnvalue(int index) const
572    {
573        return GetLocalisation_noerror(this->descriptionReturnvalue_);
574    }
575
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    */
582    /* static */ const ConsoleCommand* ConsoleCommand::getCommand(const std::string& group, const std::string& name, bool bPrintError)
583    {
584        // find the group
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())
587        {
588            // find the name
589            std::map<std::string, ConsoleCommand*>::const_iterator it_name = it_group->second.find(name);
590            if (it_name != it_group->second.end())
591            {
592                // return the pointer
593                return it_name->second;
594            }
595        }
596        if (bPrintError)
597        {
598            if (group == "")
599                COUT(1) << "Error: Couldn't find console command with shortcut \"" << name << "\"" << std::endl;
600            else
601                COUT(1) << "Error: Couldn't find console command with group \"" << group << "\" and name \"" << name << "\"" << std::endl;
602        }
603        return 0;
604    }
605
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    */
612    /* static */ const ConsoleCommand* ConsoleCommand::getCommandLC(const std::string& group, const std::string& name, bool bPrintError)
613    {
614        std::string groupLC = getLowercase(group);
615        std::string nameLC = getLowercase(name);
616
617        // find the group
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())
620        {
621            // find the name
622            std::map<std::string, ConsoleCommand*>::const_iterator it_name = it_group->second.find(nameLC);
623            if (it_name != it_group->second.end())
624            {
625                // return the pointer
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
639    /**
640        @brief Returns the static map that stores all console commands.
641    */
642    /* static */ std::map<std::string, std::map<std::string, ConsoleCommand*> >& ConsoleCommand::getCommandMap()
643    {
644        static std::map<std::string, std::map<std::string, ConsoleCommand*> > commandMap;
645        return commandMap;
646    }
647
648    /**
649        @brief Returns the static map that stores all console commands in lowercase.
650    */
651    /* static */ std::map<std::string, std::map<std::string, ConsoleCommand*> >& ConsoleCommand::getCommandMapLC()
652    {
653        static std::map<std::string, std::map<std::string, ConsoleCommand*> > commandMapLC;
654        return commandMapLC;
655    }
656
657    /**
658        @brief Registers a new command with given group an name by adding it to the command map.
659    */
660    /* static */ void ConsoleCommand::registerCommand(const std::string& group, const std::string& name, ConsoleCommand* command)
661    {
662        if (name == "")
663            return;
664
665        // check if a command with this name already exists
666        if (ConsoleCommand::getCommand(group, name) != 0)
667        {
668            if (group == "")
669                COUT(2) << "Warning: A console command with shortcut \"" << name << "\" already exists." << std::endl;
670            else
671                COUT(2) << "Warning: A console command with name \"" << name << "\" already exists in group \"" << group << "\"." << std::endl;
672        }
673        else
674        {
675            // add the command to the map
676            ConsoleCommand::getCommandMap()[group][name] = command;
677            ConsoleCommand::getCommandMapLC()[getLowercase(group)][getLowercase(name)] = command;
678        }
679    }
680
681    /**
682        @brief Removes the command from the command map.
683    */
684    /* static */ void ConsoleCommand::unregisterCommand(ConsoleCommand* command)
685    {
686        // iterate through all groups
687        for (std::map<std::string, std::map<std::string, ConsoleCommand*> >::iterator it_group = ConsoleCommand::getCommandMap().begin(); it_group != ConsoleCommand::getCommandMap().end(); )
688        {
689            // iterate through all commands of each group
690            for (std::map<std::string, ConsoleCommand*>::iterator it_name = it_group->second.begin(); it_name != it_group->second.end(); )
691            {
692                // erase the command
693                if (it_name->second == command)
694                    it_group->second.erase(it_name++);
695                else
696                    ++it_name;
697            }
698
699            // erase the group if it is empty now
700            if (it_group->second.empty())
701                ConsoleCommand::getCommandMap().erase(it_group++);
702            else
703                ++it_group;
704        }
705
706        // now the same for the lowercase-map:
707
708        // iterate through all groups
709        for (std::map<std::string, std::map<std::string, ConsoleCommand*> >::iterator it_group = ConsoleCommand::getCommandMapLC().begin(); it_group != ConsoleCommand::getCommandMapLC().end(); )
710        {
711            // iterate through all commands of each group
712            for (std::map<std::string, ConsoleCommand*>::iterator it_name = it_group->second.begin(); it_name != it_group->second.end(); )
713            {
714                // erase the command
715                if (it_name->second == command)
716                    it_group->second.erase(it_name++);
717                else
718                    ++it_name;
719            }
720
721            // erase the group if it is empty now
722            if (it_group->second.empty())
723                ConsoleCommand::getCommandMapLC().erase(it_group++);
724            else
725                ++it_group;
726        }
727    }
728
729    /**
730        @brief Deletes all commands
731    */
732    /* static */ void ConsoleCommand::destroyAll()
733    {
734        // delete entries until the map is empty
735        while (!ConsoleCommand::getCommandMap().empty() && !ConsoleCommand::getCommandMap().begin()->second.empty())
736            delete ConsoleCommand::getCommandMap().begin()->second.begin()->second;
737    }
738}
Note: See TracBrowser for help on using the repository browser.