Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/archive/tutorial2/src/libraries/core/command/ConsoleCommand.h

Last change on this file was 8858, checked in by landauf, 13 years ago

merged output branch back to trunk.

Changes:

  • you have to include util/Output.h instead of util/Debug.h
  • COUT(x) is now called orxout(level)
  • output levels are now defined by an enum instead of numbers. see util/Output.h for the definition
  • it's possible to use output contexts with orxout(level, context). see util/Output.h for some common contexts. you can define more contexts
  • you must use 'endl' at the end of an output message, '\n' does not flush the message

Output levels:

  • instead of COUT(0) use orxout()
  • instead of COUT(1) use orxout(user_error) or orxout(internal_error)
  • instead of COUT(2) use orxout(user_warning) or orxout(internal_warning)
  • instead of COUT(3) use orxout(user_status/user_info) or orxout(internal_status/internal_info)
  • instead of COUT(4) use orxout(verbose)
  • instead of COUT(5) use orxout(verbose_more)
  • instead of COUT(6) use orxout(verbose_ultra)

Guidelines:

  • user_* levels are for the user, visible in the console and the log-file
  • internal_* levels are for developers, visible in the log-file
  • verbose_* levels are for debugging, only visible if the context of the output is activated

Usage in C++:

  • orxout() << "message" << endl;
  • orxout(level) << "message" << endl;
  • orxout(level, context) << "message" << endl;

Usage in Lua:

  • orxout("message")
  • orxout(orxonox.level.levelname, "message")
  • orxout(orxonox.level.levelname, "context", "message")

Usage in Tcl (and in the in-game-console):

  • orxout levelname message
  • orxout_context levelname context message
  • shortcuts: log message, error message, warning message, status message, info message, debug message
  • Property svn:eol-style set to native
File size: 39.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/**
30    @defgroup ConsoleCommand Console commands
31    @ingroup Command
32*/
33
34/**
35    @file
36    @ingroup Command ConsoleCommand
37    @brief Declaration of the orxonox::ConsoleCommand class and the SetConsoleCommand() macro.
38
39    @anchor ConsoleCommandExample
40
41    Console commands can be used to write scripts, use key-bindings or simply to be
42    entered into the shell by the user. Instances of orxonox::ConsoleCommand define
43    the function of a command, and also more information like, for example, if it is
44    active, default values, and possible arguments.
45
46    Commands need to be registered to the system statically on startup by using the
47    SetConsoleCommand() or DeclareConsoleCommand() macros outside of a function.
48    This ensures that commands are known to the system at any time, so they can be
49    evaluated (see orxonox::CommandExecutor::evaluate()), for example for key-bindings.
50
51    Example:
52    @code
53    void myCoutFunction(const std::string& text)        // Define a static function
54    {
55        orxout() << "Text: " << text << endl;           // Print the text to the console
56    }
57
58    SetConsoleCommand("cout", &myCoutFunction);         // Register the function as command with name "cout"
59    @endcode
60
61    Now you can open the shell and execute the command:
62    @code
63    $ cout Hello World
64    @endcode
65
66    Internally this command is now passed to orxonox::CommandExecutor::execute():
67    @code
68    CommandExecutor::execute("cout HelloWorld");
69    @endcode
70
71    CommandExecutor searches for a command with name "cout" and passes the arguments
72    "Hello World" to it. Because we registered myCoutFunction() with this command,
73    as a result the following text will be printed to the console:
74    @code
75    Text: Hello World
76    @endcode
77
78    You can add more attributes to the ConsoleCommand, by using the command-chain feature
79    of SetConsoleCommand(). For example like this:
80    @code
81    SetConsoleCommand("cout", &myCoutFunction)
82        .addGroup("output", "text")
83        .accessLevel(AccessLevel::Offline)
84        .defaultValues("no text");
85    @endcode
86
87    Open the shell again and try it:
88    @code
89    $ cout Hello World
90    Text: Hello World
91    $ output text Hello World
92    Text: Hello World
93    $ cout
94    Text: no text
95    @endcode
96
97    If you execute it online (note: the access level is "Offline"), you will see the
98    following (or something similar):
99    @code
100    $ cout Hello World
101    Error: Can't execute command "cout", access denied.
102    @endcode
103
104    If a command is executed, the arguments are passed to an underlying function,
105    whitch is wrapped by an orxonox::Functor which again is wrapped by an orxonox::Executor.
106    The Functor contains the function-pointer, as well as the object-pointer in
107    case of a non-static member-function. The executor stores possible default-values
108    for each argument of the function.
109
110    The function of a command can be changed at any time. It's possible to just exchange
111    the function-pointer of the underlying Functor if the headers of the functions are
112    exactly the same. But you can also exchange the Functor itself or even completely
113    replace the Executor. Also the other attributes of a ConsoleCommand can be modified
114    during the game, for example it can be activated or deactivated.
115
116    To do so, the function ModifyConsoleCommand() has to be used. It returns an instance
117    of orxonox::ConsoleCommand::ConsoleCommandManipulator which has an interface similar to
118    orxonox::ConsoleCommand, but with slight differences. You can use it the same way like
119    SetConsoleCommand(), meaning you can use command-chains to change different attributes at
120    the same time. ModifyConsoleCommand() must not be executed statically, but rather in a
121    function at some point of the execution of the program.
122
123    Example:
124    @code
125    void myOtherCoutFunction(const std::string& text)                       // Define a new static function
126    {
127        orxout() << "Uppercase: " << getUppercase(text) << endl;            // Print the text in uppercase to the console
128    }
129
130    {
131        // ...                                                              // somewhere in the code
132
133        ModifyConsoleCommand("cout").setFunction(&myOtherCoutFunction);     // Modify the underlying function of the command
134
135        // ...
136    }
137    @endcode
138
139    If you now enter the command into the shell, you'll see a different behavior:
140    @code
141    $ cout Hello World
142    Uppercase: HELLO WORLD
143    $ cout
144    Uppercase: NO TEXT
145    @endcode
146
147    A few important notes about changing functions:
148
149    Instead of changing the function with setFunction(), you can also create a command-stack
150    by using pushFunction() and popFunction(). It's important to note a few things about that,
151    because the underlying structure of Executor and Functor has a few pitfalls:
152     - If you push a new function-pointer, the same executor as before will be used (and, if
153       the headers match, even the same functor can be used, which is very fast)
154     - If you push a new Functor, the same executor as before will be used
155     - If you push a new Executor, everything is changed
156
157    Note that the executor contains the @b default @b values, so if you just exchange the
158    Functor, the default values remain the same. However if you decide to change the default
159    values at any point of the stack, <b>this will also change the default values on all
160    other stack-levels</b> that share the same executor. If you don't like this behavior,
161    you have to explicitly push a new executor before changing the default values, either by
162    calling pushFunction(executor) or by calling pushFunction(void) which pushes a copy of
163    the current executor to the stack.
164
165    Another important point are object pointers in case of non-static member-functions.
166    Whenever you set or push a new function, <b>you must add the object pointer again</b>
167    because objects are stored in the Functor which is usually exchanged if you change
168    the function.
169
170    You can also use a stack for objects, but note that this <b>object-stack is different for each
171    function</b> - so if you set a new function, the object-stack will be cleared. If you push
172    a new function, the old object-stack is stored in the stack, so it can be restored if
173    you pop the function.
174
175    %DeclareConsoleCommand():
176
177    Appart from SetConsoleCommand() you can also call DeclareConsoleCommand(). In contrast
178    to SetConsoleCommand(), this doesn't assign a function to the command. Indeed you have
179    to pass a function-pointer to DeclareConsoleCommand(), but it is only used to determine
180    the header of the future command-function. This allows to declare a command statically,
181    thus it's possible to evaluate key-bindings of this command, but the actual function
182    can be assigned at a later point.
183
184    Example:
185    @code
186    DeclareConsoleCommand("cout", &prototype::void__string);
187    @endcode
188
189    If you try to execute the command now, you see the following (or something similar):
190    @code
191    $ cout Hello World
192    Error: Can't execute command "cout", command is not active.
193    @endcode
194
195    You first have to assign a function to use the command:
196    @code
197    {
198        // ...
199
200        ModifyConsoleCommand("cout").setFunction(&myCoutFunction);
201
202        // ...
203    }
204    @endcode
205
206    Now you can use it:
207    @code
208    $ cout Hello World
209    Text: Hello World
210    @endcode
211
212    Note that the initial function prototype::void__string is defined in the namespace
213    orxonox::prototype. If there's no function with the desired header, you can extend
214    the collection of functions or simply use another function that has the same header.
215*/
216
217#ifndef _ConsoleCommand_H__
218#define _ConsoleCommand_H__
219
220#include "core/CorePrereqs.h"
221
222#include <stack>
223#include <vector>
224#include <boost/preprocessor/cat.hpp>
225#include <boost/preprocessor/facilities/expand.hpp>
226
227#include "util/VA_NARGS.h"
228#include "ArgumentCompletionFunctions.h"
229#include "Executor.h"
230
231
232/**
233    @brief Defines a console command. The macro is overloaded for 2-4 parameters.
234
235    This is an overloaded macro. Depending on the number of arguments a different
236    overloaded implementation of the macro will be chosen.
237
238    Console commands created with SetConsoleCommand() become active immediately and
239    the given function-pointer (and optionally the object) will be used to execute
240    the command.
241*/
242#define SetConsoleCommand(...) \
243    BOOST_PP_EXPAND(BOOST_PP_CAT(SetConsoleCommand, ORXONOX_VA_NARGS(__VA_ARGS__))(__VA_ARGS__))
244/**
245    @brief This macro is executed if you call SetConsoleCommand() with 2 arguments.
246    @param name The name (string) of the console command
247    @param functionpointer The function-pointer of the corresponding command-function
248*/
249#define SetConsoleCommand2(name, functionpointer) \
250    SetConsoleCommandGeneric("", name, orxonox::createFunctor(functionpointer))
251/**
252    @brief This macro is executed if you call SetConsoleCommand() with 3 arguments.
253    @param group The group (string) of the console command
254    @param name The name (string) of the console command
255    @param functionpointer The function-pointer of the corresponding command-function
256*/
257#define SetConsoleCommand3(group, name, functionpointer) \
258    SetConsoleCommandGeneric(group, name, orxonox::createFunctor(functionpointer))
259/**
260    @brief This macro is executed if you call SetConsoleCommand() with 4 arguments.
261    @param group The group (string) of the console command
262    @param name The name (string) of the console command
263    @param functionpointer The function-pointer of the corresponding command-function
264    @param object The object that will be assigned to the command. Used for member-functions.
265*/
266#define SetConsoleCommand4(group, name, functionpointer, object) \
267    SetConsoleCommandGeneric(group, name, orxonox::createFunctor(functionpointer, object))
268
269/// Internal macro
270#define SetConsoleCommandGeneric(group, name, functor) \
271    static orxonox::ConsoleCommand& BOOST_PP_CAT(__consolecommand_, __UNIQUE_NUMBER__) = (*orxonox::createConsoleCommand(group, name, orxonox::createExecutor(functor)))
272
273
274/**
275    @brief Declares a console command. The macro is overloaded for 2-3 parameters.
276
277    This is an overloaded macro. Depending on the number of arguments a different
278    overloaded implementation of the macro will be chosen.
279
280    Console commands created with DeclareConsoleCommand() don't use the the given
281    function-pointer to execute the command, it is only used to define the header
282    of the future command-function. The command is inactive until you manually
283    set a function with orxonox::ModifyConsoleCommand(). You can use a different
284    function-pointer than in the final command, as long as it has the same header.
285*/
286#define DeclareConsoleCommand(...) \
287    BOOST_PP_EXPAND(BOOST_PP_CAT(DeclareConsoleCommand, ORXONOX_VA_NARGS(__VA_ARGS__))(__VA_ARGS__))
288/**
289    @brief This macro is executed if you call DeclareConsoleCommand() with 2 arguments.
290    @param name The name (string) of the console command
291    @param functionpointer The function-pointer of an arbitrary function that has the same header as the final function
292*/
293#define DeclareConsoleCommand2(name, functionpointer) \
294    DeclareConsoleCommandGeneric("", name, orxonox::createFunctor(functionpointer))
295/**
296    @brief This macro is executed if you call DeclareConsoleCommand() with 3 arguments.
297    @param group The group (string) of the console command
298    @param name The name (string) of the console command
299    @param functionpointer The function-pointer of an arbitrary function that has the same header as the final function
300*/
301#define DeclareConsoleCommand3(group, name, functionpointer) \
302    DeclareConsoleCommandGeneric(group, name, orxonox::createFunctor(functionpointer))
303
304/// Internal macro
305#define DeclareConsoleCommandGeneric(group, name, functor) \
306    static orxonox::ConsoleCommand& BOOST_PP_CAT(__consolecommand_, __UNIQUE_NUMBER__) = (*orxonox::createConsoleCommand(group, name, orxonox::createExecutor(functor), false))
307
308
309namespace orxonox
310{
311    /**
312        @brief A small collection of functions that can be used in DeclareConsoleCommand() if
313        you don't want to use the real function-pointer.
314    */
315    namespace prototype
316    {
317        inline void void__void(void) {}
318        inline void void__string(const std::string&) {}
319
320        inline std::string string__bool(bool) { return ""; }
321        inline std::string string__string(const std::string&) { return ""; }
322        inline std::string string__uint_uint_bool(unsigned int, unsigned int, bool) { return ""; }
323    }
324
325    namespace AccessLevel
326    {
327        /**
328            @brief Possible access levels: A command can only be executed if the program is in the state which is requested by the access level.
329        */
330        enum Enum
331        {
332            All,
333            Standalone,
334            Master,
335            Server,
336            Client,
337            Online,
338            Offline,
339            None
340        };
341    }
342
343    /**
344        @brief The ConsoleCommand class stores all information about a console command which can be executed by CommandExecutor.
345
346        Console commands can be entered by the user into the shell, called in scripts, or
347        used for key-bindings. They are simple text strings that can be executed by
348        CommandExecutor. CommandExecutor will search for a ConsoleCommand with the given
349        group and name and will execute it's Executor (which again calls the Functor and
350        this finally calls the command-function).
351
352        @see See @ref ConsoleCommandExample "ConsoleCommand.h" for more information and some examples.
353    */
354    class _CoreExport ConsoleCommand
355    {
356        friend struct ConsoleCommandManipulator;
357
358        /**
359            @brief Helper class that is used to put the current state of the ConsoleCommand on a stack.
360        */
361        struct Command
362        {
363            ExecutorPtr executor_;              ///< The executor
364            FunctorPtr functor_;                ///< The function that is used with the executor - has to be stored separatley because the executor is often used with different functors
365            std::vector<void*> objectStack_;    ///< The object stack
366        };
367
368        public:
369            /**
370                @brief Helper class that is used to manipulate console commands.
371
372                An instance of this class is returned if you call the ModifyConsoleCommand macro.
373                This class provides an interface which wraps some functions of ConsoleCommand. It
374                allows access to some private functions like setFunction() (that can't be called
375                right after SetConsoleCommand()) but it also hides some functions that shouln't be
376                called after the static declaration like addShortcut() or description().
377
378                @see See @ref ConsoleCommandExample "ConsoleCommand.h" for more information and examples.
379            */
380            struct ConsoleCommandManipulator
381            {
382                public:
383                    /// Constructor: Creates a manipulator for a given ConsoleCommand.
384                    ConsoleCommandManipulator(const ConsoleCommand* command) : command_(const_cast<ConsoleCommand*>(command)) {}
385
386                    /// Changes the current function of the command. @param function The new function-pointer @param bForce If true, the new function-pointer is always assigned, even if the headers don't match
387                    template <class F>
388                    inline ConsoleCommandManipulator& setFunction(F function, bool bForce = false)
389                        {
390                            if (this->command_)
391                            {
392                                // check if the headers match. If they do, only change the function-pointer of the current Functor instead of creating a new Functor
393                                if (this->command_->getExecutor() && this->command_->getExecutor()->getFunctor() && this->command_->getExecutor()->getFunctor()->getFullIdentifier() == typeid(F))
394                                {
395                                    FunctorPointer<F>* functor = static_cast<FunctorPointer<F>*>(this->command_->getExecutor()->getFunctor().get());
396                                    functor->setFunction(function);
397                                    return *this;
398                                }
399                                this->command_->setFunction(createFunctor(function), bForce);
400                            }
401                            return *this;
402                        }
403                    /// Changes the current function of the command. @param function The new function-pointer @param object The new object-pointer (for member-functions) @param bForce If true, the new function-pointer is always assigned, even if the headers don't match
404                    template <class F, class O>
405                    inline ConsoleCommandManipulator& setFunction(F function, O* object, bool bForce = false)
406                        {
407                            if (this->command_)
408                            {
409                                // check if the headers match. If they do, only change the function-pointer of the current Functor instead of creating a new Functor
410                                if (this->command_->getExecutor() && this->command_->getExecutor()->getFunctor() && this->command_->getExecutor()->getFunctor()->getFullIdentifier() == typeid(F))
411                                {
412                                    FunctorPointer<F, O>* functor = static_cast<FunctorPointer<F, O>*>(this->command_->getExecutor()->getFunctor().get());
413                                    functor->setFunction(function);
414                                    functor->setObject(object);
415                                    return *this;
416                                }
417                                this->command_->setFunction(createFunctor(function, object), bForce);
418                            }
419                            return *this;
420                        }
421                    /// Changes the current Functor of the command. @param functor The new Functor @param bForce If true, the new Functor is always assigned, even if the headers don't match
422                    inline ConsoleCommandManipulator& setFunction(const FunctorPtr& functor, bool bForce = false)
423                        { if (this->command_) { this->command_->setFunction(functor, bForce); } return *this; }
424                    /// Changes the current Executor of the command. @param executor The new Executor @param bForce If true, the new Executor is always assigned, even if the headers don't match
425                    inline ConsoleCommandManipulator& setFunction(const ExecutorPtr& executor, bool bForce = false)
426                        { if (this->command_) { this->command_->setFunction(executor, bForce); } return *this; }
427
428                    /// Pushes a copy of the current Executor on the command-stack, that can be altered without changing the old Executor. @details This function is especially useful if you don't wan't to change the function, but only the default values of the executor.
429                    inline ConsoleCommandManipulator& pushFunction()
430                        { if (this->command_) { this->command_->pushFunction(); } return *this; }
431                    /// Pushes a new function on the command-stack. @param function The new function-pointer @param bForce If true, the new function-pointer is always assigned, even if the headers don't match
432                    template <class F>
433                    inline ConsoleCommandManipulator& pushFunction(F function, bool bForce = false)
434                        { if (this->command_) { this->command_->pushFunction(createFunctor(function), bForce); } return *this; }
435                    /// Pushes a new function on the command-stack. @param function The new function-pointer @param object The new object-pointer (for member-functions) @param bForce If true, the new function-pointer is always assigned, even if the headers don't match
436                    template <class F, class O>
437                    inline ConsoleCommandManipulator& pushFunction(F function, O* object, bool bForce = false)
438                        { if (this->command_) { this->command_->pushFunction(createFunctor(function, object), bForce); } return *this; }
439                    /// Pushes a new Functor on the command-stack. @param functor The new Functor @param bForce If true, the new Functor is always assigned, even if the headers don't match
440                    inline ConsoleCommandManipulator& pushFunction(const FunctorPtr& functor, bool bForce = false)
441                        { if (this->command_) { this->command_->pushFunction(functor, bForce); } return *this; }
442                    /// Pushes a new Executor on the command-stack. @param executor The new Executor @param bForce If true, the new Executor is always assigned, even if the headers don't match
443                    inline ConsoleCommandManipulator& pushFunction(const ExecutorPtr& executor, bool bForce = false)
444                        { if (this->command_) { this->command_->pushFunction(executor, bForce); } return *this; }
445
446                    /// Removes the current function from the stack and restores the old state. If there's no other function on the stack, the command is deactivated.
447                    inline ConsoleCommandManipulator& popFunction()
448                        { if (this->command_) { this->command_->popFunction(); } return *this; }
449
450                    /// Sets the current function-pointer to NULL, which also deactivates the command.
451                    inline ConsoleCommandManipulator& resetFunction()
452                        { if (this->command_) { this->command_->resetFunction(); } return *this; }
453
454                    /// Changes the current object (used for member-functions).
455                    inline ConsoleCommandManipulator& setObject(void* object)
456                        { if (this->command_) { this->command_->setObject(object); } return *this; }
457                    /// Pushes a new object on the object-stack.
458                    inline ConsoleCommandManipulator& pushObject(void* object)
459                        { if (this->command_) { this->command_->pushObject(object); } return *this; }
460                    /// Removes the current object from the object-stack and restores the old object (or NULL if there's no object left on the stack).
461                    inline ConsoleCommandManipulator& popObject()
462                        { if (this->command_) { this->command_->popObject(); } return *this; }
463
464                    /// Changes the activity of the command.
465                    inline ConsoleCommandManipulator& setActive(bool bActive)
466                        { if (this->command_) { this->command_->setActive(bActive); } return *this; }
467                    /// Activates the command.
468                    inline ConsoleCommandManipulator& activate()
469                        { return this->setActive(true); }
470                    /// Deactivates the command.
471                    inline ConsoleCommandManipulator& deactivate()
472                        { return this->setActive(false); }
473
474                    /// Changes the visibility of the command.
475                    inline ConsoleCommandManipulator& setHidden(bool bHidden)
476                        { if (this->command_) { this->command_->setHidden(bHidden); } return *this; }
477                    /// Hides the command (can still be executed, but is not visible in the list of available commands).
478                    inline ConsoleCommandManipulator& hide()
479                        { return this->setHidden(true); }
480                    /// Makes the command visible.
481                    inline ConsoleCommandManipulator& show()
482                        { return this->setHidden(false); }
483
484                    /// Changes the default values of the current executor (doesn't modify executors on deeper levels of the command-stack).
485                    inline ConsoleCommandManipulator& defaultValues(const MultiType& arg1)
486                        { if (this->command_) { this->command_->defaultValues(arg1); } return *this; }
487                    /// Changes the default values of the current executor (doesn't modify executors on deeper levels of the command-stack).
488                    inline ConsoleCommandManipulator& defaultValues(const MultiType& arg1, const MultiType& arg2)
489                        { if (this->command_) { this->command_->defaultValues(arg1, arg2); } return *this; }
490                    /// Changes the default values of the current executor (doesn't modify executors on deeper levels of the command-stack).
491                    inline ConsoleCommandManipulator& defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3)
492                        { if (this->command_) { this->command_->defaultValues(arg1, arg2, arg3); } return *this; }
493                    /// Changes the default values of the current executor (doesn't modify executors on deeper levels of the command-stack).
494                    inline ConsoleCommandManipulator& defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4)
495                        { if (this->command_) { this->command_->defaultValues(arg1, arg2, arg3, arg4); } return *this; }
496                    /// Changes the default values of the current executor (doesn't modify executors on deeper levels of the command-stack).
497                    inline ConsoleCommandManipulator& defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4, const MultiType& arg5)
498                        { if (this->command_) { this->command_->defaultValues(arg1, arg2, arg3, arg4, arg5); } return *this; }
499                    /// Changes the default value of the argument with given index of the current executor (doesn't modify executors on deeper levels of the command-stack).
500                    inline ConsoleCommandManipulator& defaultValue(unsigned int index, const MultiType& arg)
501                        { if (this->command_) { this->command_->defaultValue(index, arg); } return *this; }
502
503                    /// Changes the access level of the command.
504                    inline ConsoleCommandManipulator& accessLevel(AccessLevel::Enum level)
505                        { if (this->command_) { this->command_->accessLevel(level); } return *this; }
506
507                    /// Changes the argument completer for the given parameter.
508                    inline ConsoleCommandManipulator& argumentCompleter(unsigned int index, ArgumentCompleter* completer)
509                        { if (this->command_) { this->command_->argumentCompleter(index, completer); } return *this; }
510
511                    /// Defines the command to be an input command.
512                    inline ConsoleCommandManipulator& setAsInputCommand()
513                        { if (this->command_) { this->command_->setAsInputCommand(); } return *this; }
514                    /// Changes the keybind mode of the command.
515                    inline ConsoleCommandManipulator& keybindMode(KeybindMode::Value mode)
516                        { if (this->command_) { this->command_->changeKeybindMode(mode); } return *this; }
517                    /// Sets the input configured param to the given index.
518                    inline ConsoleCommandManipulator& inputConfiguredParam(int index)
519                        { if (this->command_) { this->command_->inputConfiguredParam(index); } return *this; }
520
521                private:
522                    ConsoleCommand* command_;   ///< The command which is being manipulated by this object
523            };
524
525        public:
526            ConsoleCommand(const std::string& group, const std::string& name, const ExecutorPtr& executor, bool bInitialized = true);
527            ~ConsoleCommand();
528
529            ConsoleCommand& addShortcut();
530            ConsoleCommand& addShortcut(const std::string&  name);
531            ConsoleCommand& addGroup(const std::string& group);
532            ConsoleCommand& addGroup(const std::string& group, const std::string&  name);
533
534            /// Returns the name that was first used for this command.
535            inline const std::string& getName() const
536                { return this->baseName_; }
537
538            const ExecutorPtr& getExecutor() const;
539            /// Returns the functor that defines the required header for this command (but isn't necessarily executed).
540            inline const FunctorPtr& getBaseFunctor() const
541                { return this->baseFunctor_; }
542
543            /// Changes the activity of the command.
544            inline ConsoleCommand& setActive(bool bActive)
545                { this->bActive_ = bActive; return *this; }
546            /// Activates the command.
547            inline ConsoleCommand& activate()
548                { return this->setActive(true); }
549            /// Deactivates the command.
550            inline ConsoleCommand& deactivate()
551                { return this->setActive(false); }
552
553            /// Changes the visibility of the command.
554            inline ConsoleCommand& setHidden(bool bHidden)
555                { this->bHidden_ = bHidden; return *this; }
556            /// Hides the command (can still be executed, but is not visible in the list of available commands).
557            inline ConsoleCommand& hide()
558                { return this->setHidden(true); }
559            /// Makes the command visible.
560            inline ConsoleCommand& show()
561                { return this->setHidden(false); }
562
563            bool isActive() const;
564            bool hasAccess() const;
565            /// Returns true if the command is currently hidden.
566            inline bool isHidden() const
567                { return this->bHidden_; }
568
569            ConsoleCommand& description(const std::string& description);
570            const std::string& getDescription() const;
571
572            ConsoleCommand& descriptionParam(unsigned int index, const std::string& description);
573            const std::string& getDescriptionParam(unsigned int index) const;
574
575            ConsoleCommand& descriptionReturnvalue(const std::string& description);
576            const std::string& getDescriptionReturnvalue(int index) const;
577
578            ConsoleCommand& defaultValues(const MultiType& arg1);
579            ConsoleCommand& defaultValues(const MultiType& arg1, const MultiType& arg2);
580            ConsoleCommand& defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3);
581            ConsoleCommand& defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4);
582            ConsoleCommand& defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4, const MultiType& arg5);
583            ConsoleCommand& defaultValue(unsigned int index, const MultiType& arg);
584
585            /// Changes the access level of the command.
586            inline ConsoleCommand& accessLevel(AccessLevel::Enum level)
587                { this->accessLevel_ = level; return *this; }
588            /// Returns the access level of the command.
589            inline AccessLevel::Enum getAccessLevel() const
590                { return this->accessLevel_; }
591
592            ConsoleCommand& argumentCompleter(unsigned int index, ArgumentCompleter* completer);
593            ArgumentCompleter* getArgumentCompleter(unsigned int index) const;
594
595            /// Defines the command to be an input command
596            inline ConsoleCommand& setAsInputCommand()
597            {
598                this->keybindMode(KeybindMode::OnHold);
599                this->defaultValue(0, Vector2(0.0f, 0.0f));
600                this->inputConfiguredParam(0);
601                return *this;
602            }
603
604            /// Sets the keybind mode. Note: use changeKeybindMode if you intend to change the mode.
605            inline ConsoleCommand& keybindMode(KeybindMode::Value mode)
606                { this->keybindMode_ = mode; return *this; }
607            /// Returns the keybind mode
608            inline KeybindMode::Value getKeybindMode() const
609                { return this->keybindMode_; }
610
611            ConsoleCommand& changeKeybindMode(KeybindMode::Value mode);
612
613            /// Changes the input configured param to the given index.
614            inline ConsoleCommand& inputConfiguredParam(int index)
615                { this->inputConfiguredParam_ = index; return *this; }
616            /// Returns the input configured param.
617            inline int getInputConfiguredParam_() const
618                { return this->inputConfiguredParam_; }
619
620            /// Returns a manipulator for this command.
621            inline ConsoleCommandManipulator getManipulator() const
622                { return this; }
623
624        private:
625            bool headersMatch(const FunctorPtr& functor);
626            bool headersMatch(const ExecutorPtr& executor);
627
628            bool setFunction(const ExecutorPtr& executor, bool bForce = false);
629            bool setFunction(const FunctorPtr& functor, bool bForce = false);
630            void pushFunction(const ExecutorPtr& executor, bool bForce = false);
631            void pushFunction(const FunctorPtr& functor, bool bForce = false);
632            void pushFunction();
633            void popFunction();
634            void resetFunction();
635
636            bool setObject(void* object);
637            void pushObject(void* object);
638            void popObject();
639            void* getObject() const;
640
641            bool bActive_;                                                  ///< True if the command should be active (it can still be inactive, for example if the function is missing)
642            bool bHidden_;                                                  ///< True if the command is hidden (it is still executable, but not visible in the list of available commands)
643            AccessLevel::Enum accessLevel_;                                 ///< The access level (the state of the game in which you can access the command)
644            std::string baseName_;                                          ///< The name that was first assigned to the command
645            FunctorPtr baseFunctor_;                                        ///< The functor that defines the header of the command-function
646
647            ExecutorPtr executor_;                                          ///< The Executor that is used to execute the command
648            std::stack<Command> commandStack_;                              ///< A stack of commands, used to push and pop different functions
649            std::vector<void*> objectStack_;                                ///< A stack of objects, used to push and pop different objects for a function
650
651            ArgumentCompleter* argumentCompleter_[MAX_FUNCTOR_ARGUMENTS];   ///< ArgumentCompleter for each argument
652
653            KeybindMode::Value keybindMode_;                                ///< The keybind mode
654            int inputConfiguredParam_;                                      ///< The input configured param
655
656            LanguageEntryLabel description_;                                ///< The description of the command
657            LanguageEntryLabel descriptionReturnvalue_;                     ///< A description of the return-value
658            LanguageEntryLabel descriptionParam_[MAX_FUNCTOR_ARGUMENTS];    ///< A description for each argument
659
660        public:
661            /// Returns the map with all groups and commands.
662            static inline const std::map<std::string, std::map<std::string, ConsoleCommand*> >& getCommands()
663                { return ConsoleCommand::getCommandMap(); }
664            /// Returns the map with all groups and commands in lowercase.
665            static inline const std::map<std::string, std::map<std::string, ConsoleCommand*> >& getCommandsLC()
666                { return ConsoleCommand::getCommandMapLC(); }
667
668            /// Returns a command (shortcut) with given name. @param name The name of the command shortcut @param bPrintError If true, an error is printed if the command doesn't exist
669            static inline const ConsoleCommand* getCommand(const std::string& name, bool bPrintError = false)
670                { return ConsoleCommand::getCommand("", name, bPrintError); }
671            /// Returns a command (shortcut) with given name in lowercase. @param name The lowercase name of the command shortcut @param bPrintError If true, an error is printed if the command doesn't exist
672            static inline const ConsoleCommand* getCommandLC(const std::string& name, bool bPrintError = false)
673                { return ConsoleCommand::getCommandLC("", name, bPrintError); }
674
675            static const ConsoleCommand* getCommand(const std::string& group, const std::string& name, bool bPrintError = false);
676            static const ConsoleCommand* getCommandLC(const std::string& group, const std::string& name, bool bPrintError = false);
677
678            static void destroyAll();
679
680        private:
681            static std::map<std::string, std::map<std::string, ConsoleCommand*> >& getCommandMap();
682            static std::map<std::string, std::map<std::string, ConsoleCommand*> >& getCommandMapLC();
683
684            static void registerCommand(const std::string& group, const std::string& name, ConsoleCommand* command);
685            static void unregisterCommand(ConsoleCommand* command);
686    };
687
688    /**
689        @brief Creates a new ConsoleCommand.
690        @param name The name of the command
691        @param executor The executor of the command
692        @param bInitialized If true, the command is ready to be executed, otherwise it has to be activated first.
693    */
694    inline ConsoleCommand* createConsoleCommand(const std::string& name, const ExecutorPtr& executor, bool bInitialized = true)
695        { return new ConsoleCommand("", name, executor, bInitialized); }
696    /**
697        @brief Creates a new ConsoleCommand.
698        @param group The group of the command
699        @param name The name of the command
700        @param executor The executor of the command
701        @param bInitialized If true, the command is ready to be executed, otherwise it has to be activated first.
702    */
703    inline ConsoleCommand* createConsoleCommand(const std::string& group, const std::string& name, const ExecutorPtr& executor, bool bInitialized = true)
704        { return new ConsoleCommand(group, name, executor, bInitialized); }
705
706
707    /**
708        @brief Returns a manipulator for a command with the given name.
709
710        @note If the command doesn't exist, the manipulator contains a NULL pointer to the command,
711        but it can still be used without checks, because all functions of ConsoleCommandManipulator
712        check internally if the command exists.
713    */
714    inline ConsoleCommand::ConsoleCommandManipulator ModifyConsoleCommand(const std::string& name)
715        { return ConsoleCommand::getCommand(name, true); }
716    /**
717        @brief Returns a manipulator for a command with the given group and name.
718
719        @note If the command doesn't exist, the manipulator contains a NULL pointer to the command,
720        but it can still be used without checks, because all functions of ConsoleCommandManipulator
721        check internally if the command exists.
722    */
723    inline ConsoleCommand::ConsoleCommandManipulator ModifyConsoleCommand(const std::string& group, const std::string& name)
724        { return ConsoleCommand::getCommand(group, name, true); }
725}
726
727#endif /* _ConsoleCommand_H__ */
Note: See TracBrowser for help on using the repository browser.