Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/script_engine/script.cc @ 9216

Last change on this file since 9216 was 9061, checked in by patrick, 18 years ago

merged the single_player branche to trunk

File size: 9.8 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
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, or (at your option)
9   any later version.
10
11### File Specific:
12   main-programmer: Silvan Nellen
13   co-programmer: Benjamin Grauer
14*/
15
16#include "script.h"
17#include "script_class.h"
18#include "luaincl.h"
19
20#include "util/loading/resource_manager.h"
21
22#include "loading/load_param.h"
23#include "parser/tinyxml/tinyxml.h"
24
25#include "class_list.h"
26CREATE_SCRIPTABLE_CLASS(Script, CL_SCRIPT,
27                    addMethod("addObject", ExecutorLua2<Script,const std::string&, const std::string& >(&Script::addObject))
28                    ->addMethod("selectFunction", ExecutorLua2ret<Script, bool, const std::string&, int >(&Script::selectFunction))
29                    ->addMethod("executeFunction", ExecutorLua0ret<Script,bool >(&Script::executeFunction))
30                     );
31
32Script::Script(const TiXmlElement* root)
33{
34  this->setClassID(CL_SCRIPT, "Script");
35
36  returnCount = argumentCount = 0;
37
38  luaState = lua_open();
39
40  luaopen_base(luaState);
41  luaopen_table(luaState);
42  luaopen_io(luaState);
43  luaopen_string(luaState);
44  luaopen_math(luaState);
45  luaopen_debug(luaState);
46  if (root != NULL)
47    this->loadParams(root);
48}
49
50
51Script::~Script()
52{
53  lua_setgcthreshold(luaState, 0);  // collected garbage
54  lua_close(luaState);
55}
56
57
58void Script::loadParams(const TiXmlElement* root)
59{
60  //printf("Loading params for %p \n",this);
61  BaseObject::loadParams(root);
62
63  LOAD_PARAM_START_CYCLE(root, object);
64  {
65    LoadParam_CYCLE(object, "object", this, Script, addObject)
66        .describe("The name of an object that is needed by a script");
67  }
68  LOAD_PARAM_END_CYCLE(object);
69
70
71  LoadParam(root, "file", this, Script, loadFileNoRet)
72      .describe("the fileName of the script, that should be loaded into this world")
73      .defaultValues("");
74}
75
76
77
78bool Script::loadFile(const std::string& filename)
79 {
80   this->setName(filename);
81   std::string filedest(ResourceManager::getInstance()->getDataDir());
82   filedest += "scripts/" + filename;
83   
84   this->addThisScript();
85   this->registerStandartClasses();
86   
87   if(currentFile.length() != 0)
88   {
89     printf("Could not load %s because an other file is already loaded: %s\n",filename.c_str(), currentFile.c_str());
90     return false;
91    }
92
93   int error = luaL_loadfile (luaState, filedest.c_str());
94
95   if(error == 0)
96   {
97     
98     error = lua_pcall(luaState, 0, 0, 0);
99
100     if(error == 0)
101     {
102      currentFile = filename;
103      return true;
104     }
105     else
106     {
107       printf("ERROR while loading file %s: \n",filename.c_str());
108       reportError(error);
109     }
110
111   }
112   else
113   {
114     printf("ERROR while loading file %s: \n",filename.c_str());
115     reportError(error);
116   }
117
118   return false;
119 }
120
121
122 void Script::addObject(const std::string& className, const std::string& objectName)
123 {
124   //printf("Script %s: I am about to add %s of class %s\n",this->getName(),objectName.c_str(),className.c_str());
125
126   BaseObject* scriptClass = ClassList::getObject(className, CL_SCRIPT_CLASS);
127  // printf("The script class for %s is at %p \n",className.c_str(),scriptClass);
128   WorldObject tmpObj;
129   if (scriptClass != NULL)
130   {
131     tmpObj.type = className;
132     if( !classIsRegistered(className) )
133     {
134     static_cast<ScriptClass*>(scriptClass)->registerClass(this);
135     }
136
137     BaseObject* object = ClassList::getObject(objectName, className);
138    // printf("%s is at %p \n",objectName.c_str(),object);
139     if (object != NULL && !objectIsAdded(objectName))
140     {
141        static_cast<ScriptClass*>(scriptClass)->insertObject(this, object, false);
142        tmpObj.name = objectName;
143        registeredObjects.push_back(tmpObj);
144     }
145   }
146 }
147
148
149
150
151 bool Script::executeFile()
152 {
153   printf("WARNING: script.executeFile is not implemented yet");
154   /*if(currentFile.length() != 0)
155   {
156    int error = lua_pcall(luaState, 0, 0, 0);
157    if( error == 0)
158      return true;
159     else
160      {
161       reportError(error);
162       return false;
163      }
164 }*/
165   return false;
166 }
167
168 bool Script::selectFunction(const std::string& functionName, int retCount)
169 {
170   if(returnCount == 0 && currentFunction.length() == 0) //no return values left on the stack and no other function selected
171   {
172   lua_pushlstring(luaState, functionName.c_str(), functionName.size() );
173   lua_gettable(luaState, LUA_GLOBALSINDEX);
174
175   if(lua_isfunction( luaState , -1))
176   {
177     returnCount = retCount;
178     argumentCount = 0;
179     currentFunction = functionName;
180     return true;
181   }
182   else
183    return false;
184   }
185   else
186     printf("There is an other function active ( %s ) or there are unremoved return values on the stack. Please remove them first.\n",currentFunction.c_str());
187   return false;
188 }
189
190 //return number of returned values
191 bool Script::executeFunction()
192 {
193   if(currentFunction.length() != 0 )
194   {
195    int error = lua_pcall(luaState, argumentCount, returnCount,0);
196    if(error != 0)
197    {
198     printf("ERROR while executing function %s: \n",currentFunction.c_str());
199     reportError(error);
200     //clean up
201     currentFunction.assign("");
202     argumentCount = returnCount = 0;
203     return false;
204    }
205    else
206    {
207      currentFunction.assign("");//a function gets unusable after beeing called for the first time
208      argumentCount = 0;
209      return true;
210    }
211   }
212   else
213     printf("Error: no function selected.\n");
214
215   return false;
216 }
217
218
219 //overload this function to add different types
220 bool Script::pushParam(int param, std::string& toFunction)
221 {
222   if(currentFunction == toFunction)
223   {
224     lua_pushnumber(luaState, (lua_Number) param);
225     argumentCount++;
226     return true;
227   }
228   else
229   {
230    printf("Couldn't add parameter because the wrong function is selected: %s instead of %s\n", currentFunction.c_str(), toFunction.c_str());
231    return false;
232   }
233
234 }
235
236
237 bool Script::pushParam(float param, std::string& toFunction)
238 {
239   if(currentFunction.compare(toFunction) == 0)
240   {
241     lua_pushnumber(luaState,(lua_Number) param);
242     argumentCount++;
243     return true;
244   }
245   else
246   {
247     printf("Couldn't add parameter because the wrong function is selected: %s instead of %s\n", currentFunction.c_str(), toFunction.c_str());
248     return false;
249   }
250
251 }
252
253 bool Script::pushParam(double param, std::string& toFunction)
254 {
255   if(currentFunction.compare(toFunction) == 0)
256   {
257     lua_pushnumber(luaState,(lua_Number) param);
258     argumentCount++;
259     return true;
260   }
261   else
262   {
263     printf("Couldn't add parameter because the wrong function is selected: %s instead of %s\n", currentFunction.c_str(), toFunction.c_str());
264     return false;
265   }
266
267 }
268
269 int Script::getReturnedInt()
270 {
271   int returnValue = 0;
272   if(returnCount > 0)
273   {
274     if(lua_isnumber(luaState, -1*returnCount))
275     {
276       returnValue = (int)lua_tonumber(luaState, -1*returnCount);
277       lua_remove(luaState,-1*returnCount);
278       returnCount--;
279       
280     }
281   }
282   return returnValue;
283 }
284
285
286 bool Script::getReturnedBool()
287 {
288   bool returnValue = false;
289   if(returnCount > 0)
290   {
291     if(lua_isboolean(luaState, -1*returnCount))
292     {
293       returnValue = (bool)lua_toboolean(luaState, -1*returnCount);
294       lua_remove(luaState,-1*returnCount);
295       returnCount--;
296     }
297     else
298       printf("ERROR: Form %s : trying to retreive non bolean value",this->currentFile.c_str());
299   }
300   return returnValue;
301 }
302
303float Script::getReturnedFloat()
304 {
305   float returnValue = 0.0f;
306   if(returnCount > 0)
307   {
308     if(lua_isnumber(luaState, -1*returnCount))
309     {
310       returnValue = (float)lua_tonumber(luaState, -1*returnCount);
311       lua_remove(luaState,-1*returnCount);
312       returnCount--;
313     }
314   }
315   return returnValue;
316 }
317
318 void Script::getReturnedString(std::string& string)
319 {
320   const char* returnValue = "";
321   if(returnCount > 0)
322   {
323     if(lua_isstring(luaState, -1*returnCount))
324     {
325       returnValue = lua_tostring(luaState, -1*returnCount);
326       lua_remove(luaState,-1*returnCount);
327       returnCount--;
328     }
329   }
330  string.assign(returnValue);
331 }
332
333
334void Script::addThisScript()
335{
336  BaseObject* scriptClass = ClassList::getObject("Script", CL_SCRIPT_CLASS);
337   if (scriptClass != NULL)
338   {
339     static_cast<ScriptClass*>(scriptClass)->registerClass(this);
340     static_cast<ScriptClass*>(scriptClass)->insertObject(this, this,"thisscript", false);
341   }
342}
343
344 int Script::reportError(int error)
345 {
346 if(error != 0)
347 {
348  const char *msg = lua_tostring(luaState, -1);
349  if (msg == NULL) msg = "(error with no message)";
350  fprintf(stderr, "ERROR: %s\n", msg);
351  lua_pop(luaState, 1);
352 }
353  return error;
354 }
355
356 bool Script::registerStandartClasses()
357 {
358   bool success = false;
359   
360   //success = this->registerClass(std::string("Vector"));
361    success = this->registerClass("ScriptTrigger");
362
363   return success;
364 }
365 
366 
367 bool Script::registerClass( const std::string& className)
368 {
369   BaseObject* scriptClass = ClassList::getObject(className, CL_SCRIPT_CLASS);
370   //printf("The script class for %s is at %p \n",className.c_str(),scriptClass);
371   WorldObject tmpObj;
372   if (scriptClass != NULL)
373   {
374     tmpObj.type = className;
375     if( !classIsRegistered(className) )
376     {
377       static_cast<ScriptClass*>(scriptClass)->registerClass(this);
378       tmpObj.name = "";
379       registeredObjects.push_back(tmpObj);
380       return true;
381     }
382   }
383   return false;
384 
385 }
386
387 bool Script::classIsRegistered(const std::string& type)
388 {
389   for(std::list<WorldObject>::const_iterator it = registeredObjects.begin(); it != registeredObjects.end(); it++ )
390   {
391     if( (*it).type == type)
392     {
393       return true;
394     }
395   }
396   return false;
397 }
398
399
400
401 bool Script::objectIsAdded(const std::string& name)
402 {
403   for(std::list<WorldObject>::const_iterator it = registeredObjects.begin(); it != registeredObjects.end(); it++ )
404   {
405     if( (*it).name == name)
406     {
407       return true;
408     }
409   }
410   return false;
411
412
413 }
Note: See TracBrowser for help on using the repository browser.