Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/usability/src/libraries/core/command/ConsoleCommand.cc @ 10241

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