Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

some improvements/fixes in ConsoleCommand

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