00001 /*************************************************************************** 00002 * * 00003 * (c) Art Tevs, MPI Informatik Saarbruecken * 00004 * mailto: <tevs@mpi-sb.mpg.de> * 00005 * * 00006 * This program is free software; you can redistribute it and/or modify * 00007 * it under the terms of the GNU General Public License as published by * 00008 * the Free Software Foundation; either version 2 of the License, or * 00009 * (at your option) any later version. * 00010 * * 00011 ***************************************************************************/ 00012 00013 00014 #ifndef _NR_SCRIPT_ENGINE_H_ 00015 #define _NR_SCRIPT_ENGINE_H_ 00016 00017 00018 //---------------------------------------------------------------------------------- 00019 // Includes 00020 //---------------------------------------------------------------------------------- 00021 #include "Prerequisities.h" 00022 00023 //! Declare a scripting function as static memeber of class (c++ only) \ingroup script 00024 #define ScriptFunctionDef(name)\ 00025 public: static nrEngine::ScriptResult name (const std::vector<std::string>&, const std::vector<nrEngine::ScriptParam>&) 00026 00027 //! Declare a scripting function out of the class class (c++ only) \ingroup script 00028 #define ScriptFunctionDec(name, class)\ 00029 nrEngine::ScriptResult class::name (const std::vector<std::string>& args, const std::vector<nrEngine::ScriptParam>& param) 00030 00031 namespace nrEngine{ 00032 00033 00034 //! Each script function can return variable argument as a result \ingroup script 00035 typedef VarArg ScriptResult; 00036 00037 //! The real functions accept this default parameter \ingroup script 00038 typedef boost::any ScriptParam; 00039 00040 //! We define each function that can be called from the scripts as this type \ingroup script 00041 typedef boost::function<ScriptResult (const std::vector<std::string>&, const std::vector<ScriptParam>&)> ScriptFunctor; 00042 00043 //! Script engine is a glue code between the scripts and the engine 00044 /** 00045 * The script engine is a main class representing the glue code between 00046 * the scripting languages (from plugins or whatever) and the game engine. 00047 * The game engine will register functions by the script engine, so 00048 * you get an access to this functions in your scripts. So the script 00049 * engine class is something like an engine's API for the scripts. 00050 * 00051 * In the future we want to improve the functionality of the scripting 00052 * engine, by adding the possibility to use meta classes. So the scripts 00053 * could create new classes based on engine's. 00054 * 00055 * \ingroup script 00056 **/ 00057 class _NRExport ScriptEngine{ 00058 public: 00059 00060 /** 00061 * Cast a script parameter, which is of type "any", to any other type. 00062 * Note: we use here any_cast, so you have to worry about catching the 00063 * error throws 00064 **/ 00065 template<class T> 00066 static T parameter_cast(const ScriptParam& p){ 00067 return boost::any_cast<T>(p); 00068 } 00069 00070 /** 00071 * Register new functions, that can be called from scripts. 00072 * The functions registered here are called through call() method. 00073 * 00074 * You can also specify one default parameter, that will be passed 00075 * to the called function (e.g. pointer to your object). The parameter is 00076 * of the boost type "any". So it does not have certain type. 00077 * 00078 * @param name Name of the function, must be unique 00079 * @param func Function itself (i.e. boost::function) 00080 * @param param Parameters you want to be stored to pass later to the function 00081 * 00082 * @return either OK or an error code if there is some problems 00083 **/ 00084 Result add(const std::string& name, ScriptFunctor func, const std::vector<ScriptParam>& param = std::vector<ScriptParam>()); 00085 00086 /** 00087 * Using variable parameter arguments. 00088 * @see add() 00089 **/ 00090 Result add(const std::string& name, ScriptFunctor func, const VarArg& v); 00091 00092 /** 00093 * Delete already registered function from the api database. 00094 * 00095 * @param name name of the function to be deregistered 00096 * 00097 * @return either OK or an error code 00098 **/ 00099 Result del(const std::string& name); 00100 00101 /** 00102 * Call a certain function from the database whithin the given parameters. 00103 * First script engine database will look if there is a function 00104 * whithin the given name. Then if such could be found the functor 00105 * according to the function will be called. As first parameter it sends 00106 * the user predefined parameters, stored in the database. As second 00107 * it will pass the string parameters coming from the script or from 00108 * the subroutine called this method. 00109 * 00110 * @param name Unique name of hte function to be called 00111 * @param args Argument list of arguments given to the function (like in 00112 * the console, first must always be the function name) 00113 **/ 00114 ScriptResult call(const std::string& name, const std::vector<std::string>& args = std::vector<std::string>()); 00115 00116 /** 00117 * Load a new script from the given file. The script will be loaded 00118 * by the resource manager, which will try to find the appropriate 00119 * loader for this type of scripts. If there is no such loader could 00120 * be found, so null will be returned. Otherwise you get a resource 00121 * pointer to the script. The resource pointer garanty that the according 00122 * script will be used in the way like all other resources. This means if 00123 * a script is unloaded,so EmptyScript will be used. You do not have 00124 * to care about given pointers, because resource pointers have similar 00125 * behaviours as smart pointers. 00126 * 00127 * The function does load the scripts in the memory, so you do not have 00128 * to carry about the returned pointer, if you do not want to. Loaded scripts 00129 * are still accessable by their names. 00130 * 00131 * @param name Name for the script. 00132 * @param fileName Name of the file containign the script. 00133 * 00134 * @return ResourcePtr<IScript> to the script. 00135 **/ 00136 ResourcePtr<IScript> load(const std::string& name, const std::string& fileName); 00137 00138 /** 00139 * This method will execute script of a certain name loaded before 00140 * with loadScript() method. 00141 * 00142 * @param name Unique name for the script 00143 * @param runOnce If true the script will be executed only one time 00144 * @param immediate If true the script will be run immediately. If false 00145 * the script will be added as a task into the kernel, and will be started 00146 * in the next execution cycle. 00147 * 00148 * @return Returning code of IScript::execute() method. 00149 **/ 00150 Result execute(const std::string& name, bool runOnce = true, bool immediate = false); 00151 00152 /** 00153 * Combined method of load() and execute(). See documentation for them 00154 * instead 00155 **/ 00156 Result execute(const std::string& name, const std::string& fileName, bool runOnce = true, bool immediate = false); 00157 00158 /** 00159 * Get count of functions registered in the database 00160 **/ 00161 NR_FORCEINLINE uint32 getFunctionCount() const { return mDatabase.size(); } 00162 00163 /** 00164 * Return an functor element of a certain index from the database. 00165 * Any functor element is a pair of the functor and script parameters 00166 * defined by the user. 00167 **/ 00168 const std::string& getFunction(uint32 index, ScriptFunctor& functor); 00169 00170 private: 00171 00172 //! Run not by name, but by pointer 00173 Result _execute(const ResourcePtr<IScript>& ptr, bool runOnce = true, bool immediate = false); 00174 00175 //! Only engine is allowed to create the instances 00176 friend class Engine; 00177 00178 //! Allocate memory and define all default values 00179 ScriptEngine(); 00180 00181 //! Release used memory and close the scripting engine 00182 ~ScriptEngine(); 00183 00184 //! This is our database holding the registered functions 00185 typedef std::map<std::string, std::pair<ScriptFunctor, std::vector<ScriptParam> > > FunctionDatabase; 00186 00187 //! Here we store our registered functions 00188 FunctionDatabase mDatabase; 00189 00190 //! Check whenever a function with the given name is already in the database 00191 bool isRegistered(const std::string& name); 00192 00193 //! Get the function according to the given name 00194 FunctionDatabase::iterator get(const std::string& name); 00195 00196 00197 ScriptFunctionDef(scriptLoad); 00198 ScriptFunctionDef(scriptRun); 00199 ScriptFunctionDef(scriptLoadAndRun); 00200 ScriptFunctionDef(scriptCall); 00201 00202 }; 00203 00204 00205 }; 00206 00207 #endif