Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

progress on the new console command interface.
enhanced possibilities to compare Functors and to manipulate Executors

  • Property svn:eol-style set to native
File size: 13.6 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->baseName_ = name;
131        this->baseExecutor_ = executor;
132
133        if (bInitialized)
134            this->executor_ = executor;
135
136        _ConsoleCommand::registerCommand(group, name, this);
137    }
138
139    _ConsoleCommand::~_ConsoleCommand()
140    {
141        _ConsoleCommand::unregisterCommand(this);
142    }
143
144    _ConsoleCommand& _ConsoleCommand::addShortcut()
145    {
146        _ConsoleCommand::registerCommand("", this->baseName_, this);
147        return *this;
148    }
149
150    _ConsoleCommand& _ConsoleCommand::addShortcut(const std::string&  name)
151    {
152        _ConsoleCommand::registerCommand("", name, this);
153        return *this;
154    }
155
156    _ConsoleCommand& _ConsoleCommand::addGroup(const std::string& group)
157    {
158        _ConsoleCommand::registerCommand(group, this->baseName_, this);
159        return *this;
160    }
161
162    _ConsoleCommand& _ConsoleCommand::addGroup(const std::string& group, const std::string&  name)
163    {
164        _ConsoleCommand::registerCommand(group, name, this);
165        return *this;
166    }
167
168    bool _ConsoleCommand::isActive() const
169    {
170        return (this->bActive_ && this->executor_ && this->executor_->getFunctor());
171    }
172
173    bool _ConsoleCommand::headersMatch(const FunctorPtr& functor)
174    {
175        unsigned int minparams = std::min(this->baseExecutor_->getParamCount(), functor->getParamCount());
176
177        if (this->baseExecutor_->getFunctor()->getHeaderIdentifier(minparams) != functor->getHeaderIdentifier(minparams))
178            return false;
179        else if (functor->getParamCount() <= this->baseExecutor_->getParamCount())
180            return true;
181        else if (!this->executor_)
182            return false;
183        else
184        {
185            for (unsigned int i = this->baseExecutor_->getParamCount(); i < functor->getParamCount(); ++i)
186                if (!this->executor_->defaultValueSet(i))
187                    return false;
188
189            return true;
190        }
191    }
192
193    bool _ConsoleCommand::headersMatch(const ExecutorPtr& executor)
194    {
195        unsigned int minparams = std::min(this->baseExecutor_->getParamCount(), executor->getParamCount());
196
197        if (this->baseExecutor_->getFunctor()->getHeaderIdentifier(minparams) != executor->getFunctor()->getHeaderIdentifier(minparams))
198            return false;
199        else if (executor->getParamCount() <= this->baseExecutor_->getParamCount())
200            return true;
201        else
202        {
203            for (unsigned int i = this->baseExecutor_->getParamCount(); i < executor->getParamCount(); ++i)
204                if (!executor->defaultValueSet(i))
205                    return false;
206
207            return true;
208        }
209    }
210
211    bool _ConsoleCommand::setFunction(const ExecutorPtr& executor, bool bForce)
212    {
213        if (!executor || !executor->getFunctor() || bForce || this->headersMatch(executor))
214        {
215            this->executor_ = executor;
216            return true;
217        }
218        else
219        {
220            COUT(1) << "Error: Couldn't assign new executor to console command \"" << this->baseName_ << "\", headers don't match." << std::endl;
221            return false;
222        }
223    }
224
225    bool _ConsoleCommand::setFunction(const FunctorPtr& functor, bool bForce)
226    {
227        if (!functor || bForce || this->headersMatch(functor))
228        {
229            if (this->executor_)
230                this->executor_->setFunctor(functor);
231            else
232                this->executor_ = createExecutor(functor);
233
234            return true;
235        }
236        else
237        {
238            COUT(1) << "Error: Couldn't assign new functor to console command \"" << this->baseName_ << "\", headers don't match." << std::endl;
239            return false;
240        }
241    }
242
243    void _ConsoleCommand::pushFunction(const ExecutorPtr& executor, bool bForce)
244    {
245        Command command;
246        command.executor_ = this->getExecutor();
247        if (command.executor_)
248            command.functor_ = this->getFunctor();
249
250        if (this->setFunction(executor, bForce))
251            this->commandStack_.push(command);
252    }
253
254    void _ConsoleCommand::pushFunction(const FunctorPtr& functor, bool bForce)
255    {
256        Command command;
257        command.executor_ = this->getExecutor();
258        if (command.executor_)
259            command.functor_ = this->getFunctor();
260
261        if (this->setFunction(functor, bForce))
262            this->commandStack_.push(command);
263    }
264
265    void _ConsoleCommand::pushFunction()
266    {
267        if (this->executor_)
268            this->pushFunction(new Executor(*this->executor_.get()));
269        else
270            COUT(1) << "Error: Couldn't push copy of executor in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
271    }
272
273    void _ConsoleCommand::popFunction()
274    {
275        Command command;
276        if (!this->commandStack_.empty())
277        {
278            command = this->commandStack_.top();
279            this->commandStack_.pop();
280        }
281
282        this->executor_ = command.executor_;
283        if (command.executor_)
284            this->executor_->setFunctor(command.functor_);
285    }
286
287    const ExecutorPtr& _ConsoleCommand::getExecutor() const
288    {
289        return this->executor_;
290    }
291
292    const FunctorPtr& _ConsoleCommand::getFunctor() const
293    {
294        return this->executor_->getFunctor();
295    }
296
297    bool _ConsoleCommand::setObject(void* object)
298    {
299        if (this->executor_)
300        {
301            if (this->executor_->getFunctor())
302            {
303                this->executor_->getFunctor()->setRawObjectPointer(object);
304                return true;
305            }
306            else if (object)
307                COUT(1) << "Error: Can't assign object to console command \"" << this->baseName_ << "\", no functor set." << std::endl;
308        }
309        else if (object)
310            COUT(1) << "Error: Can't assign object to console command \"" << this->baseName_ << "\", no executor set." << std::endl;
311
312        return false;
313    }
314
315    void _ConsoleCommand::pushObject(void* object)
316    {
317        void* oldobject = this->getObject();
318        if (this->setObject(object))
319            this->objectStack_.push(oldobject);
320    }
321
322    void _ConsoleCommand::popObject()
323    {
324        void* newobject = 0;
325        if (!this->objectStack_.empty())
326        {
327            newobject = this->objectStack_.top();
328            this->objectStack_.pop();
329        }
330        this->setObject(newobject);
331    }
332
333    void* _ConsoleCommand::getObject() const
334    {
335        if (this->executor_ && this->executor_->getFunctor())
336            return this->executor_->getFunctor()->getRawObjectPointer();
337        else
338            return 0;
339    }
340
341    /* static */ const _ConsoleCommand* _ConsoleCommand::getCommand(const std::string& group, const std::string& name, bool bPrintError)
342    {
343        std::map<std::string, std::map<std::string, _ConsoleCommand*> >::const_iterator it_group = _ConsoleCommand::getCommandMap().find(group);
344        if (it_group != _ConsoleCommand::getCommandMap().end())
345        {
346            std::map<std::string, _ConsoleCommand*>::const_iterator it_name = it_group->second.find(name);
347            if (it_name != it_group->second.end())
348            {
349                return it_name->second;
350            }
351        }
352        if (bPrintError)
353        {
354            if (group == "")
355                COUT(1) << "Error: Couldn't find console command with shortcut \"" << name << "\"" << std::endl;
356            else
357                COUT(1) << "Error: Couldn't find console command with group \"" << group << "\" and name \"" << name << "\"" << std::endl;
358        }
359        return 0;
360    }
361
362    /* static */ std::map<std::string, std::map<std::string, _ConsoleCommand*> >& _ConsoleCommand::getCommandMap()
363    {
364        static std::map<std::string, std::map<std::string, _ConsoleCommand*> > commandMap;
365        return commandMap;
366    }
367
368    /* static */ void _ConsoleCommand::registerCommand(const std::string& group, const std::string& name, _ConsoleCommand* command)
369    {
370        if (name == "")
371            return;
372
373        if (_ConsoleCommand::getCommand(group, name) != 0)
374        {
375            if (group == "")
376                COUT(2) << "Warning: A console command with shortcut \"" << name << "\" already exists." << std::endl;
377            else
378                COUT(2) << "Warning: A console command with name \"" << name << "\" already exists in group \"" << group << "\"." << std::endl;
379        }
380        else
381        {
382            _ConsoleCommand::getCommandMap()[group][name] = command;
383        }
384    }
385
386    /* static */ void _ConsoleCommand::unregisterCommand(_ConsoleCommand* command)
387    {
388        for (std::map<std::string, std::map<std::string, _ConsoleCommand*> >::iterator it_group = _ConsoleCommand::getCommandMap().begin(); it_group != _ConsoleCommand::getCommandMap().end(); )
389        {
390            for (std::map<std::string, _ConsoleCommand*>::iterator it_name = it_group->second.begin(); it_name != it_group->second.end(); )
391            {
392                if (it_name->second == command)
393                    it_group->second.erase(it_name++);
394                else
395                    ++it_name;
396            }
397
398            if (it_group->second.empty())
399                _ConsoleCommand::getCommandMap().erase(it_group++);
400            else
401                ++it_group;
402        }
403    }
404}
Note: See TracBrowser for help on using the repository browser.