source: nrEngine/include/IScript.h @ 23

Revision 23, 13.0 KB checked in by art, 13 years ago (diff)
Line 
1/***************************************************************************
2 *                                                                         *
3 *   (c) Art Tevs, MPI Informatik Saarbruecken                             *
4 *       mailto: <tevs@mpi-sb.mpg.de>                                      *
5 *                                                                         *
6 *   This program is free software; you can redistribute it and/or modify  *
7 *   it under the terms of the GNU General Public License as published by  *
8 *   the Free Software Foundation; either version 2 of the License, or     *
9 *   (at your option) any later version.                                   *
10 *                                                                         *
11 ***************************************************************************/
12
13
14#ifndef _NR_SCRIPT_INTERFACE_RESOURCE__H_
15#define _NR_SCRIPT_INTERFACE_RESOURCE__H_
16
17
18//----------------------------------------------------------------------------------
19// Includes
20//----------------------------------------------------------------------------------
21#include "Prerequisities.h"
22#include "Resource.h"
23#include "ITask.h"
24
25/*!
26 * \defgroup script Engine Scripting
27 *
28 * Scripting is our form of data driven design of our engine. Scripts
29 * are also resources that are loaded through specified loader. Scripts are
30 * used to program the engine from the outside of the source code. You are
31 * able to program the engine in the runtime by executing the scripts through
32 * a console provided by the engine. To understand what the scripts are good for
33 * use appropriate literature from the internet.
34 *
35 * Our engine is designed to be very expandable and generic, so we are not use
36 * specific kind of script language. nrEngine does only provide an interface
37 * for a script classes that are implemented by plugins. The main idea of such
38 * an interface is to create a binding between the script language and the engine.
39 *
40 * The plugins classes have to know how to bind the specific script language with
41 * the script interface of the engine. The console will acquire a script object to
42 * be used for the console scripting. This script object is provided by the plugins
43 * so it uses that language which is implemented in the plugin.
44 *
45 * If there no plugins providing a scripting language so the default one is used.
46 * The default scripting language does not support anything except of some function calls.
47 * This very simple languge can be used to load another script language or
48 * to setup some properties of the engine.
49 *
50 * Because there is thousands of scripting languages outside and they can be bounded
51 * on different ways we do not provide any bounding routine. If you using any scripting
52 * language in your application, than you have to bind your code with the script code by your
53 * self. Mostly this is done through metaprogramming or through preproccessing
54 * routines on the scripting language. Therefor providing such an interface through
55 * plugins for the engine seems not to be managable. Therefor all default functions used
56 * in our engine are registered by the script engine. By adding or deleting any
57 * script function there will be an event. Your glue-code has to catch this event to
58 * take care off registering or derigistering this function in your scripting language.
59 *
60 * For example you want to use lua in your application. You use some 3rd party tools
61 * like tolua which does generate a c++ code form pkg files. This newly generated files
62 * can be used to provide your c++ classes in lua. Now to provide the engine's scripting
63 * functions, which are registered by the ScriptEngine you have to write a wrapper which will
64 * call ScriptEngine::call() method if appropriate function was called from lua.
65 *
66 * Probalby in later version we can provide some binding to you (loadtime plugins), which
67 * does provide this functionality. But at now there is no other way to do this.
68 **/
69 
70namespace nrEngine{
71       
72
73        //! Script interface for any kind of script languages
74        /**
75        * This is an interface for any kind of scripting language provided by the plugins.
76        * This interface is used to executed strings typed in the console or readed from
77        * the scripting files.
78        *
79        * We also define each script as an task in the kernel. So the script will be
80        * updated in each tick by the kernel and will be unloaded from the task queue as soon
81        * as the script ends his execution. Using of scripts as a task has the advantage, that
82        * we are able to run scripts with a certain priority/order number. So the script_Task can
83        * run before certain application task or after them.
84        *
85        * Each script can not only be executed, but if specify any functions or routines,
86        * so this routines could be explicitely called. You can also specify arguments
87        * for such a routine. Therefor the IScript interface does only store
88        * the arguments and their type as a string. Derived class should read this
89        * and pass the parameters in the right way. If a derived script language
90        * does not support any arguments or function calling so just ignore them.
91        * Passed parameters will be automaticaly removed from the waiting list as
92        * soon as the function from the script will be called.
93        *
94        * @see IResource, ITask
95        * \ingroup script
96        **/
97        class _NRExport IScript : public IResource, public ITask{
98                public:
99                        //! You can also push a list of arguments to the function directly
100                        typedef std::list<std::pair<std::string, std::string> > ArgumentList;
101
102                        /**
103                         * Returns the content of the script file
104                         **/
105                        NR_FORCEINLINE const std::string& getContent() const { return mContent; }
106                       
107                        /**
108                        * Load a script from string. The given string should contain
109                        * the script in the appropriate language, so it can be executed.
110                        *
111                        * @param str String containing the script
112                        * @return either OK or:
113                        *               - SCRIPT_PARSE_ERROR
114                        **/
115                        virtual Result loadFromString(const std::string& str) = 0;
116       
117                        /**
118                        * Get short description of the last error.
119                        **/
120                        std::string popLastError();
121       
122                        /**
123                         * Execute the script. The script will be executed completely, before
124                         * go back to the system run. Execution is done by adding the script to
125                         * the kernel's pipeline. In the next cycle the script will be then executed.
126                         *
127                         * @param runOnce If true, so the script method run() will be called only
128                         *                      once. If you specify false, so run() will be called in each
129                         *                      kernel cycle.
130                         *
131                         * NOTE: If you want to execute script immidiately, use forceExecute() instead
132                         **/
133                        Result execute(bool runOnce = true);
134
135                        /**
136                         * Force starting the script. Script will be added to the kernel
137                         * and started immeiately after that, by calling the run() method.
138                         * Afer that the script will be updated in each cycle if not otherwise
139                         * specified.
140                         *
141                         * @see execute()
142                         **/
143                        Result forceExecute(bool runOnce = true);
144
145                        /**
146                         * By calling the execute() method you will execute the whole script completely.
147                         * This is usefull if you do not interested in the results of the scripts, but
148                         * in its handling. However if you wish to call a certain function from the script
149                         * (only if function calling is supported by the scripting language), so you
150                         * have to use this method.
151                         *
152                         * Here a certain function from the script will be called. The result of this function
153                         * will be given back in a generic type ScriptResult. You have to know how
154                         * to interpret the results given back by the script. If any error occurs the
155                         * error message will be logged and an exception will be thrown. Catch
156                         * the exception to handle the errors.
157                         *
158                         * @param funcName Name of the function to call
159                         *
160                         * @return result from the script execution converted into generic
161                         * ScriptResult object.
162                         *
163                         * NOTE: To pass parameters to function use pushArgument()
164                         **/
165                        ScriptResult call(const std::string& funcName);
166 
167                        /**
168                         * User application can also specify certain arguments for functions
169                         * in the script. The derived class implementing specific script
170                         * language must read out this values before starting the script.
171                         * The derived class should also know how to pass them to the script
172                         * language and how to parse them. If a script does not support function
173                         * calling or argument binding, so this values can be ignored.
174                         *
175                         * @param funcName Name of the function/routine in the script for which one
176                         *                                      the parameters are specified
177                         * @param type String containing the name of the type of the argument
178                         * @param value String containing the value of the argument.
179                         *
180                         * @return Number of arguments currently stored for the given function including
181                         *                      the new argument.
182                         *
183                         * NOTE: Push arguments from the first to the last.
184                         **/
185                        uint32 pushArgument(const std::string& funcName, const std::string& type, const std::string& value);
186
187                        /**
188                         * Same as pushArgument() but set argument from the list. Already pushed
189                         * arguments will be removed !
190                         **/
191                        uint32 setArguments(const std::string& funcName, const ArgumentList& args);
192                       
193                        /**
194                         * Derived class should use this function to pop the first parameter
195                         * from the list. The argument type and the value will be stored in
196                         * the given variables. The function does return the number of
197                         * remaining parameters. If function returns 0, so no parameters are
198                         * available.
199                         *
200                         * @param funcName Name of the function for which the arguments are retrieved
201                         * @param type Here the type of the argument will be stored
202                         * @param value Here the value of the argument will be stored
203                         *
204                         * @return Number of remaining arguments for the function. If the resulting
205                         *                      value is -1, so no parameters for the function exists
206                         *
207                         * NOTE: The arguments are returned from the first to the last
208                         **/
209                        int32 popArgument(const std::string& funcName, std::string& type, std::string& value);
210
211                protected:
212
213                        /**
214                         * Run the script. This method must be overriden by the derived classes.
215                         * run will be called by the execution of the script. However you can not
216                         * be sure if the script executed completely or only stepwise by this method,
217                         * this depends only on the implementation. Read appropriate documentation of
218                         * script language implementation.
219                         **/
220                        virtual Result run() = 0;
221
222                        /**
223                         * Derived class can overload this method if a implemented script language
224                         * does support function calling. Default behaviour of this method
225                         * is not to call any function or to execute a script. Overload
226                         * this if you wish to have another behaviour.
227                         *
228                         * @param funcName name of the function to call
229                         * @param result Store here the result of a call of a function
230                         * @return OK if no error during the execution occurs or an error code.
231                         *                      If any error code will be returned so an exception will
232                         *                      be thrown.
233                         **/
234                        virtual Result callfunc(const std::string& funcName, ScriptResult& result);
235
236                        /**
237                         * If any error occurs stor here the error messages.
238                         * The base class will deliver them to the user. Also the base
239                         * class does implement error message stack, so returned messages are
240                         * automaticaly removed from the message stack.
241                         **/
242                        void pushErrorMessage(const std::string& msg);
243                       
244                        /**
245                         * Initialize the script interface
246                         * Specify also the script type name, so we know of which
247                         * type is the given script
248                         **/
249                        IScript(const std::string&);
250
251                        /**
252                         * Virtual destructor
253                         **/
254                        virtual ~IScript();
255                       
256                        /**
257                         * Run one step from the script. This method will be automaticaly
258                         * called from the engine's kernel.
259                         **/
260                        Result updateTask();
261
262                        //! Here we store the whole script as a string
263                        std::string mContent;
264                                                                       
265                        /**
266                         * Bypass the IResource::unloadRes() function, so that derived
267                         * class can overload them
268                         **/
269                        virtual Result unloadRes() {return OK;}
270                       
271                        //! Check if script should only run once
272                        bool shouldRunOnce() const { return mbRunOnce; }
273                       
274                        //! Should the script run only once (no loop)
275                        void setRunOnce(bool b) { mbRunOnce = b; }
276                         
277                        /**
278                         * This method will be called to check from base class to
279                         * check if run completes. If derived class returns false,
280                         * so script will be removed from the kernel
281                         **/
282                        virtual bool hasCommands() = 0;
283                       
284                private:
285
286                        //! Should this script run once
287                        bool mbRunOnce;
288                       
289                        //! Store here error messages
290                        std::list<std::string> mErrorMsg;
291                       
292                        typedef std::map<std::string, ArgumentList>             ArgumentDatabase;
293                       
294                        //! Notify if the resource was reloaded
295                        void notifyResReloaded();
296
297                        //! Here we store the arguments for the script
298                        ArgumentDatabase mArguments;
299
300        };
301
302       
303        //! Empty script object that just do nothing(idle).
304        /**
305         * Empty script objects do nothing. They idle.
306         * \ingroup script
307         **/
308        class _NRExport EmptyScript : public IScript{
309        public:
310       
311                //! Constructor does not call anything
312                EmptyScript();
313               
314                //! Release used memory
315                ~EmptyScript();
316
317                //! Loading an empty script from file does not affect anything
318                Result loadFromString(const std::string& str);
319
320                //! Executing of empty script does return immideately
321                Result run();
322
323        private:
324                bool hasCommands() { return false; }
325        };
326       
327};
328
329#endif
Note: See TracBrowser for help on using the repository browser.