source: nrEngine/src/ScriptEngine.cpp @ 22

Revision 22, 8.8 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//----------------------------------------------------------------------------------
15// Includes
16//----------------------------------------------------------------------------------
17#include "ScriptEngine.h"
18#include "Log.h"
19#include "events/EngineEvent.h"
20#include "EventManager.h"
21#include "VariadicArgument.h"
22#include "IScript.h"
23
24namespace nrEngine{
25
26        //----------------------------------------------------------------------------------
27        ScriptFunctionDec(scriptLoad, ScriptEngine)
28        {
29                // check parameter count
30                if (args.size() < 2){
31                        return ScriptResult(std::string("Not valid parameter count! Parameters (name, filename)"));
32                }
33
34                // get parameters
35                IResourcePtr ptr = Engine::sScriptEngine()->load(args[1], args[2]);
36
37                if (ptr.isNull())
38                {
39                        return ScriptResult(std::string("Can not load script ") + args[1] + " from file " + args[2]);
40                }
41
42                return ScriptResult();
43        }
44
45        //----------------------------------------------------------------------------------
46        ScriptFunctionDec(scriptRun, ScriptEngine)
47        {
48                // check parameter count
49                if (args.size() < 1){
50                        return ScriptResult(std::string("Not valid parameter count! Parameters (name [, runonce = true [, immediate = false]])"));
51                }
52
53                // get parameters
54                try{
55                        const std::string& name = args[1];
56                        bool once = true;
57                        if (args.size() > 2) once = boost::lexical_cast<bool>(args[2]);
58                        bool force = false;
59                        if (args.size() > 3) force = boost::lexical_cast<bool>(args[3]);
60
61                        // run
62                        if (!Engine::sScriptEngine()->execute(name, once, force))
63                                return ScriptResult(std::string("Can not execute script ") + name);
64                }catch(boost::bad_lexical_cast s){
65                        return ScriptResult(std::string("Wrong parameter value! "));
66                }
67               
68                return ScriptResult();
69        }
70
71        //----------------------------------------------------------------------------------
72        ScriptFunctionDec(scriptCall, ScriptEngine)
73        {
74                // check parameter count
75                if (args.size() < 2){
76                        return ScriptResult(std::string("Not valid parameter count! Parameters (name, funcname, [, param1, ..., paramn])"));
77                }
78               
79                IScript::ArgumentList ar;
80                       
81                // we get parameters, so extract them
82                if (args.size() >= 3 )
83                {
84                        for (uint32 i=3; i < args.size(); i++)
85                        {
86                                // get value
87                                std::string param = args[i];
88                               
89                                // check if it contains ':' character
90                                std::string::size_type pos = param.find(':');
91                                if (pos == std::string::npos)
92                                {
93                                        char msg[4096];
94                                        sprintf(msg, "ScriptEngine: Parameter %s does not contain type information", param.c_str());
95                                        return ScriptResult(std::string(msg));
96                                }
97                               
98                                // split on that character
99                                std::string type = param.substr(pos + 1);
100                                std::string value = param.substr(0, pos);
101       
102                                // store them
103                                ar.push_back(std::pair<std::string, std::string>(type, value));
104                        } 
105                }
106
107                // get resource
108                ResourcePtr<IScript> ptr = Engine::sResourceManager()->getByName(args[1]);
109                if (ptr.isNull())
110                        return ScriptResult(std::string("Can not find script ") + args[1]);
111
112                // now prepare arguments
113                ptr->setArguments(args[2], ar);
114                ScriptResult res;
115                ptr->call(args[2]);
116               
117                // call a specific function
118                return res;
119        }
120       
121        //----------------------------------------------------------------------------------
122        ScriptEngine::ScriptEngine(){
123                mDatabase["scriptLoad"].first = scriptLoad;
124                mDatabase["scriptRun"].first = scriptRun;
125                mDatabase["scriptExecute"].first = scriptRun;
126                mDatabase["scriptCall"].first = scriptCall;
127        }
128
129        //----------------------------------------------------------------------------------
130        ScriptEngine::~ScriptEngine(){
131
132                // empty the database
133                mDatabase.clear();
134
135        }
136
137        //----------------------------------------------------------------------------------
138        Result ScriptEngine::add(const std::string& name, ScriptFunctor func, const std::vector<ScriptParam>& param)
139        {
140                // first check whenever such function already registered
141                if (isRegistered(name))
142                        return SCRIPT_FUNCTION_REGISTERED;
143
144                // now add the function to the database
145                mDatabase[name].first = func;
146                mDatabase[name].second = param;
147
148                // some statistical information
149                NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "ScriptEngine: New function \"%s\" registered", name.c_str());
150
151                // emit a new event
152                SharedPtr<Event> msg(new ScriptRegisterFunctionEvent(name, func));
153                Engine::sEventManager()->emitSystem(msg);
154               
155                return OK;
156        }
157
158        //----------------------------------------------------------------------------------
159        Result ScriptEngine::add(const std::string& name, ScriptFunctor func, const VarArg& v){
160
161                // get the elements and store them in vector
162                std::vector<ScriptParam> p;
163                v.convert<ScriptParam>(p);
164
165                // OK
166                return add(name, func, p);
167        }
168
169        //----------------------------------------------------------------------------------
170        Result ScriptEngine::del(const std::string& name)
171        {
172                // get the function
173                FunctionDatabase::iterator it = mDatabase.find(name);
174                if (it == mDatabase.end()) return SCRIPT_FUNCTION_NOT_REGISTERED;
175
176                mDatabase.erase(it);
177
178                // some statistical information
179                NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "ScriptEngine: Function \"%s\" was removed", name.c_str());
180
181                // emit a new event
182                SharedPtr<Event> msg(new ScriptRemoveFunctionEvent(name));
183                Engine::sEventManager()->emitSystem(msg);
184
185                return OK;
186        }
187
188        //----------------------------------------------------------------------------------
189        ScriptResult ScriptEngine::call(const std::string& name, const std::vector<std::string>& args)
190        {
191                // if no such function was found
192                FunctionDatabase::iterator f = get(name);
193                if (f == mDatabase.end()){
194                        NR_Log(Log::LOG_ENGINE, Log::LL_WARNING, "ScriptEngine: Function \"%s\" was not found!", name.c_str());
195                        return ScriptResult();
196                }
197                NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "ScriptEngine: Call \"%s\" function!", name.c_str());
198
199                // call the function
200                return ((*f).second).first(args, (*f).second.second);
201        }
202
203        //----------------------------------------------------------------------------------
204        bool ScriptEngine::isRegistered(const std::string& name)
205        {
206                // search for that name in the database
207                FunctionDatabase::const_iterator it = mDatabase.find(name);
208                return it != mDatabase.end();
209        }
210
211        //----------------------------------------------------------------------------------
212        ScriptEngine::FunctionDatabase::iterator ScriptEngine::get(const std::string& name)
213        {
214                // search for that name in the database
215                FunctionDatabase::iterator it = mDatabase.find(name);
216
217                return it;
218        }
219
220        //------------------------------------------------------------------------
221        ResourcePtr<IScript> ScriptEngine::load(const std::string& name, const std::string& file)
222        {
223                // try to load the resource and check for the error code
224                ResourcePtr<IScript> plg = Engine::sResourceManager()->loadResource(name, "Scripts", file);
225
226                if (plg.isNull()){
227                        NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "Can not load the script %s from %s", name.c_str(), file.c_str());
228                }
229                return plg;
230        }
231
232
233        //------------------------------------------------------------------------
234        Result ScriptEngine::execute(const std::string& name, bool runOnce, bool immediate)
235        {
236                // get the pointer to the script resource
237                ResourcePtr<IScript> scr = Engine::sResourceManager()->getByName(name);
238                return _execute(scr, runOnce, immediate);               
239        }
240
241        //------------------------------------------------------------------------
242        Result ScriptEngine::execute(const std::string& name, const std::string& fileName, bool runOnce, bool immediate)
243        {
244                ResourcePtr<IScript> scr = load(name, fileName);
245                return _execute(scr, runOnce, immediate);
246        }
247
248        //------------------------------------------------------------------------
249        Result ScriptEngine::_execute(const ResourcePtr<IScript>& ptr, bool runOnce, bool immediate)
250        {
251                if (ptr.isNull()) return RES_NOT_FOUND;
252                if (immediate) return ptr->forceExecute(runOnce);
253                return ptr->execute(runOnce);
254        }
255
256        //------------------------------------------------------------------------
257        const std::string& ScriptEngine::getFunction(uint32 index, ScriptFunctor& functor)
258        {
259                NR_ASSERT(index < getFunctionCount());
260                FunctionDatabase::const_iterator it = mDatabase.begin();
261                for (uint32 i = 0; i < index; i++, it++){}
262
263                functor = it->second.first;
264                return it->first;
265        }
266
267};
268
Note: See TracBrowser for help on using the repository browser.