Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/presentation/src/lib/script_engine/script.cc @ 9217

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

scripttrigger can be created form within a script

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