Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/single_player_map/src/lib/script_engine/script.cc @ 9016

Last change on this file since 9016 was 9016, checked in by snellen, 18 years ago

made script scriptable

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