Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Merged inputdevice-branch back to trunk: New ScriptTrigger (ActionTrigger) available

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