Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/consolecommands3/src/libraries/core/command/ConsoleCommand.cc @ 7215

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

new console command interface now supports all functions of the old implementation

  • Property svn:eol-style set to native
File size: 18.9 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#include "ConsoleCommand.h"
30#include <cassert>
31
32#include "util/Convert.h"
33#include "core/Language.h"
34
35namespace orxonox
36{
37    ConsoleCommand::ConsoleCommand(const FunctorPtr& functor, const std::string& name) : Executor(functor, name)
38    {
39        this->accessLevel_ = AccessLevel::None;
40        this->argumentCompleter_[0] = 0;
41        this->argumentCompleter_[1] = 0;
42        this->argumentCompleter_[2] = 0;
43        this->argumentCompleter_[3] = 0;
44        this->argumentCompleter_[4] = 0;
45
46        this->keybindMode_ = KeybindMode::OnPress;
47        this->inputConfiguredParam_ = -1;
48    }
49
50    ConsoleCommand& ConsoleCommand::argumentCompleter(unsigned int param, ArgumentCompleter* completer)
51    {
52        if (param < 5)
53            this->argumentCompleter_[param] = completer;
54        else
55        {
56            COUT(2) << "Warning: Couldn't add autocompletion-function for param " << param << ": index out of bound." << std::endl;
57        }
58        return (*this);
59    }
60
61    ArgumentCompleter* ConsoleCommand::getArgumentCompleter(unsigned int param) const
62    {
63        if (param < 5)
64            return this->argumentCompleter_[param];
65        else
66            return 0;
67    }
68
69    void ConsoleCommand::createArgumentCompletionList(unsigned int param, const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4, const std::string& param5)
70    {
71        if (param < 5 && this->argumentCompleter_[param])
72            this->argumentList_ = (*this->argumentCompleter_[param])(param1, param2, param3, param4, param5);
73        else
74            this->argumentList_.clear();
75    }
76
77    ConsoleCommand& ConsoleCommand::description(const std::string& description)
78    {
79        this->description_ = std::string("ConsoleCommandDescription::" + this->name_ + "::function");
80        AddLanguageEntry(this->description_, description);
81        return (*this);
82    }
83
84    const std::string& ConsoleCommand::getDescription() const
85    {
86        return GetLocalisation_noerror(this->description_);
87    }
88
89    ConsoleCommand& ConsoleCommand::descriptionParam(unsigned int param, const std::string& description)
90    {
91        if (param < MAX_FUNCTOR_ARGUMENTS)
92        {
93            this->descriptionParam_[param] = std::string("ConsoleCommandDescription::" + this->name_ + "::param" + multi_cast<std::string>(param));
94            AddLanguageEntry(this->descriptionParam_[param], description);
95        }
96        return (*this);
97    }
98
99    const std::string& ConsoleCommand::getDescriptionParam(unsigned int param) const
100    {
101        if (param < MAX_FUNCTOR_ARGUMENTS)
102            return GetLocalisation_noerror(this->descriptionParam_[param]);
103
104        return this->descriptionParam_[0];
105    }
106
107    ConsoleCommand& ConsoleCommand::descriptionReturnvalue(const std::string& description)
108    {
109        this->descriptionReturnvalue_ = std::string("ConsoleCommandDescription::" + this->name_ + "::returnvalue");
110        AddLanguageEntry(this->descriptionReturnvalue_, description);
111        return (*this);
112    }
113
114    const std::string& ConsoleCommand::getDescriptionReturnvalue(int param) const
115    {
116        return GetLocalisation_noerror(this->descriptionReturnvalue_);
117    }
118}
119
120#include "core/BaseObject.h" // remove this
121
122namespace orxonox
123{
124    _SetConsoleCommand("BaseObject", "setName", &BaseObject::setName, (BaseObject*)0);
125    _ConsoleCommand::_ConsoleCommandManipulator test(_ModifyConsoleCommand("BaseObject", "setName").setFunction(&BaseObject::setActive));
126
127    _ConsoleCommand::_ConsoleCommand(const std::string& group, const std::string& name, const ExecutorPtr& executor, bool bInitialized)
128    {
129        this->bActive_ = true;
130        this->bHidden_ = false;
131        this->accessLevel_ = AccessLevel::All;
132
133        this->baseName_ = name;
134        this->baseExecutor_ = executor;
135
136        this->argumentCompleter_[0] = 0;
137        this->argumentCompleter_[1] = 0;
138        this->argumentCompleter_[2] = 0;
139        this->argumentCompleter_[3] = 0;
140        this->argumentCompleter_[4] = 0;
141
142        this->keybindMode_ = KeybindMode::OnPress;
143        this->inputConfiguredParam_ = -1;
144
145        if (bInitialized)
146            this->executor_ = executor;
147
148        _ConsoleCommand::registerCommand(group, name, this);
149    }
150
151    _ConsoleCommand::~_ConsoleCommand()
152    {
153        _ConsoleCommand::unregisterCommand(this);
154    }
155
156    _ConsoleCommand& _ConsoleCommand::addShortcut()
157    {
158        _ConsoleCommand::registerCommand("", this->baseName_, this);
159        return *this;
160    }
161
162    _ConsoleCommand& _ConsoleCommand::addShortcut(const std::string&  name)
163    {
164        _ConsoleCommand::registerCommand("", name, this);
165        return *this;
166    }
167
168    _ConsoleCommand& _ConsoleCommand::addGroup(const std::string& group)
169    {
170        _ConsoleCommand::registerCommand(group, this->baseName_, this);
171        return *this;
172    }
173
174    _ConsoleCommand& _ConsoleCommand::addGroup(const std::string& group, const std::string&  name)
175    {
176        _ConsoleCommand::registerCommand(group, name, this);
177        return *this;
178    }
179
180    bool _ConsoleCommand::isActive() const
181    {
182        return (this->bActive_ && this->executor_ && this->executor_->getFunctor());
183    }
184
185    bool _ConsoleCommand::headersMatch(const FunctorPtr& functor)
186    {
187        unsigned int minparams = std::min(this->baseExecutor_->getParamCount(), functor->getParamCount());
188
189        if (this->baseExecutor_->getFunctor()->getHeaderIdentifier(minparams) != functor->getHeaderIdentifier(minparams))
190            return false;
191        else if (functor->getParamCount() <= this->baseExecutor_->getParamCount())
192            return true;
193        else if (!this->executor_)
194            return false;
195        else
196        {
197            for (unsigned int i = this->baseExecutor_->getParamCount(); i < functor->getParamCount(); ++i)
198                if (!this->executor_->defaultValueSet(i))
199                    return false;
200
201            return true;
202        }
203    }
204
205    bool _ConsoleCommand::headersMatch(const ExecutorPtr& executor)
206    {
207        unsigned int minparams = std::min(this->baseExecutor_->getParamCount(), executor->getParamCount());
208
209        if (this->baseExecutor_->getFunctor()->getHeaderIdentifier(minparams) != executor->getFunctor()->getHeaderIdentifier(minparams))
210            return false;
211        else if (executor->getParamCount() <= this->baseExecutor_->getParamCount())
212            return true;
213        else
214        {
215            for (unsigned int i = this->baseExecutor_->getParamCount(); i < executor->getParamCount(); ++i)
216                if (!executor->defaultValueSet(i))
217                    return false;
218
219            return true;
220        }
221    }
222
223    bool _ConsoleCommand::setFunction(const ExecutorPtr& executor, bool bForce)
224    {
225        if (!executor || !executor->getFunctor() || bForce || this->headersMatch(executor))
226        {
227            this->executor_ = executor;
228            return true;
229        }
230        else
231        {
232            COUT(1) << "Error: Couldn't assign new executor to console command \"" << this->baseName_ << "\", headers don't match." << std::endl;
233            return false;
234        }
235    }
236
237    bool _ConsoleCommand::setFunction(const FunctorPtr& functor, bool bForce)
238    {
239        if (!functor || bForce || this->headersMatch(functor))
240        {
241            if (this->executor_)
242                this->executor_->setFunctor(functor);
243            else
244                this->executor_ = createExecutor(functor);
245
246            return true;
247        }
248        else
249        {
250            COUT(1) << "Error: Couldn't assign new functor to console command \"" << this->baseName_ << "\", headers don't match." << std::endl;
251            return false;
252        }
253    }
254
255    void _ConsoleCommand::pushFunction(const ExecutorPtr& executor, bool bForce)
256    {
257        Command command;
258        command.executor_ = this->getExecutor();
259        if (command.executor_)
260            command.functor_ = this->getExecutor()->getFunctor();
261
262        if (this->setFunction(executor, bForce))
263            this->commandStack_.push(command);
264    }
265
266    void _ConsoleCommand::pushFunction(const FunctorPtr& functor, bool bForce)
267    {
268        Command command;
269        command.executor_ = this->getExecutor();
270        if (command.executor_)
271            command.functor_ = this->getExecutor()->getFunctor();
272
273        if (this->setFunction(functor, bForce))
274            this->commandStack_.push(command);
275    }
276
277    void _ConsoleCommand::pushFunction()
278    {
279        if (this->executor_)
280            this->pushFunction(new Executor(*this->executor_.get()));
281        else
282            COUT(1) << "Error: Couldn't push copy of executor in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
283    }
284
285    void _ConsoleCommand::popFunction()
286    {
287        Command command;
288        if (!this->commandStack_.empty())
289        {
290            command = this->commandStack_.top();
291            this->commandStack_.pop();
292        }
293
294        this->executor_ = command.executor_;
295        if (command.executor_)
296            this->executor_->setFunctor(command.functor_);
297    }
298
299    const ExecutorPtr& _ConsoleCommand::getExecutor() const
300    {
301        return this->executor_;
302    }
303
304    bool _ConsoleCommand::setObject(void* object)
305    {
306        if (this->executor_)
307        {
308            if (this->executor_->getFunctor())
309            {
310                this->executor_->getFunctor()->setRawObjectPointer(object);
311                return true;
312            }
313            else if (object)
314                COUT(1) << "Error: Can't assign object to console command \"" << this->baseName_ << "\", no functor set." << std::endl;
315        }
316        else if (object)
317            COUT(1) << "Error: Can't assign object to console command \"" << this->baseName_ << "\", no executor set." << std::endl;
318
319        return false;
320    }
321
322    void _ConsoleCommand::pushObject(void* object)
323    {
324        void* oldobject = this->getObject();
325        if (this->setObject(object))
326            this->objectStack_.push(oldobject);
327    }
328
329    void _ConsoleCommand::popObject()
330    {
331        void* newobject = 0;
332        if (!this->objectStack_.empty())
333        {
334            newobject = this->objectStack_.top();
335            this->objectStack_.pop();
336        }
337        this->setObject(newobject);
338    }
339
340    void* _ConsoleCommand::getObject() const
341    {
342        if (this->executor_ && this->executor_->getFunctor())
343            return this->executor_->getFunctor()->getRawObjectPointer();
344        else
345            return 0;
346    }
347
348    _ConsoleCommand& _ConsoleCommand::defaultValues(const MultiType& param1)
349    {
350        if (this->executor_)
351            this->executor_->setDefaultValues(param1);
352        else
353            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
354
355        return *this;
356    }
357
358    _ConsoleCommand& _ConsoleCommand::defaultValues(const MultiType& param1, const MultiType& param2)
359    {
360        if (this->executor_)
361            this->executor_->setDefaultValues(param1, param2);
362        else
363            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
364
365        return *this;
366    }
367
368    _ConsoleCommand& _ConsoleCommand::defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3)
369    {
370        if (this->executor_)
371            this->executor_->setDefaultValues(param1, param2, param3);
372        else
373            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
374
375        return *this;
376    }
377
378    _ConsoleCommand& _ConsoleCommand::defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4)
379    {
380        if (this->executor_)
381            this->executor_->setDefaultValues(param1, param2, param3, param4);
382        else
383            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
384
385        return *this;
386    }
387
388    _ConsoleCommand& _ConsoleCommand::defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5)
389    {
390        if (this->executor_)
391            this->executor_->setDefaultValues(param1, param2, param3, param4, param5);
392        else
393            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
394
395        return *this;
396    }
397
398    _ConsoleCommand& _ConsoleCommand::defaultValue(unsigned int index, const MultiType& param)
399    {
400        if (this->executor_)
401            this->executor_->setDefaultValue(index, param);
402        else
403            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
404
405        return *this;
406    }
407
408    _ConsoleCommand& _ConsoleCommand::argumentCompleter(unsigned int param, ArgumentCompleter* completer)
409    {
410        if (param < 5)
411            this->argumentCompleter_[param] = completer;
412        else
413            COUT(2) << "Warning: Couldn't add autocompletion-function for param " << param << " in console command \"" << this->baseName_ << "\": index out of bound." << std::endl;
414
415        return *this;
416    }
417
418    ArgumentCompleter* _ConsoleCommand::getArgumentCompleter(unsigned int param) const
419    {
420        if (param < 5)
421            return this->argumentCompleter_[param];
422        else
423            return 0;
424    }
425
426    void _ConsoleCommand::createArgumentCompletionList(unsigned int param, const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4, const std::string& param5)
427    {
428        if (param < 5 && this->argumentCompleter_[param])
429            this->argumentList_ = (*this->argumentCompleter_[param])(param1, param2, param3, param4, param5);
430        else
431            this->argumentList_.clear();
432    }
433
434    _ConsoleCommand& _ConsoleCommand::description(const std::string& description)
435    {
436        this->description_ = std::string("ConsoleCommandDescription::" + this->baseName_ + "::function");
437        AddLanguageEntry(this->description_, description);
438        return *this;
439    }
440
441    const std::string& _ConsoleCommand::getDescription() const
442    {
443        return GetLocalisation_noerror(this->description_);
444    }
445
446    _ConsoleCommand& _ConsoleCommand::descriptionParam(unsigned int param, const std::string& description)
447    {
448        if (param < MAX_FUNCTOR_ARGUMENTS)
449        {
450            this->descriptionParam_[param] = std::string("ConsoleCommandDescription::" + this->baseName_ + "::param" + multi_cast<std::string>(param));
451            AddLanguageEntry(this->descriptionParam_[param], description);
452        }
453        return *this;
454    }
455
456    const std::string& _ConsoleCommand::getDescriptionParam(unsigned int param) const
457    {
458        if (param < MAX_FUNCTOR_ARGUMENTS)
459            return GetLocalisation_noerror(this->descriptionParam_[param]);
460
461        return this->descriptionParam_[0];
462    }
463
464    _ConsoleCommand& _ConsoleCommand::descriptionReturnvalue(const std::string& description)
465    {
466        this->descriptionReturnvalue_ = std::string("ConsoleCommandDescription::" + this->baseName_ + "::returnvalue");
467        AddLanguageEntry(this->descriptionReturnvalue_, description);
468        return *this;
469    }
470
471    const std::string& _ConsoleCommand::getDescriptionReturnvalue(int param) const
472    {
473        return GetLocalisation_noerror(this->descriptionReturnvalue_);
474    }
475
476    /* static */ const _ConsoleCommand* _ConsoleCommand::getCommand(const std::string& group, const std::string& name, bool bPrintError)
477    {
478        std::map<std::string, std::map<std::string, _ConsoleCommand*> >::const_iterator it_group = _ConsoleCommand::getCommandMap().find(group);
479        if (it_group != _ConsoleCommand::getCommandMap().end())
480        {
481            std::map<std::string, _ConsoleCommand*>::const_iterator it_name = it_group->second.find(name);
482            if (it_name != it_group->second.end())
483            {
484                return it_name->second;
485            }
486        }
487        if (bPrintError)
488        {
489            if (group == "")
490                COUT(1) << "Error: Couldn't find console command with shortcut \"" << name << "\"" << std::endl;
491            else
492                COUT(1) << "Error: Couldn't find console command with group \"" << group << "\" and name \"" << name << "\"" << std::endl;
493        }
494        return 0;
495    }
496
497    /* static */ std::map<std::string, std::map<std::string, _ConsoleCommand*> >& _ConsoleCommand::getCommandMap()
498    {
499        static std::map<std::string, std::map<std::string, _ConsoleCommand*> > commandMap;
500        return commandMap;
501    }
502
503    /* static */ void _ConsoleCommand::registerCommand(const std::string& group, const std::string& name, _ConsoleCommand* command)
504    {
505        if (name == "")
506            return;
507
508        if (_ConsoleCommand::getCommand(group, name) != 0)
509        {
510            if (group == "")
511                COUT(2) << "Warning: A console command with shortcut \"" << name << "\" already exists." << std::endl;
512            else
513                COUT(2) << "Warning: A console command with name \"" << name << "\" already exists in group \"" << group << "\"." << std::endl;
514        }
515        else
516        {
517            _ConsoleCommand::getCommandMap()[group][name] = command;
518        }
519    }
520
521    /* static */ void _ConsoleCommand::unregisterCommand(_ConsoleCommand* command)
522    {
523        for (std::map<std::string, std::map<std::string, _ConsoleCommand*> >::iterator it_group = _ConsoleCommand::getCommandMap().begin(); it_group != _ConsoleCommand::getCommandMap().end(); )
524        {
525            for (std::map<std::string, _ConsoleCommand*>::iterator it_name = it_group->second.begin(); it_name != it_group->second.end(); )
526            {
527                if (it_name->second == command)
528                    it_group->second.erase(it_name++);
529                else
530                    ++it_name;
531            }
532
533            if (it_group->second.empty())
534                _ConsoleCommand::getCommandMap().erase(it_group++);
535            else
536                ++it_group;
537        }
538    }
539}
Note: See TracBrowser for help on using the repository browser.