Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/script_engine/OLD/Script.cc @ 8230

Last change on this file since 8230 was 8061, checked in by bensch, 18 years ago

merged the scriptengine back to the trunk

File size: 12.0 KB
RevLine 
[7654]1#include <cassert>
[7645]2#include <string>
[7654]3#include <iostream>
[7655]4#include "luaincl.h"
[7645]5
6#include "Script.h"
7#include "RestoreStack.h"
8#include "This.h"
9#include "LuaCallback.h"
10
11// ---------------------------------------------------------------------------
12
[7653]13namespace OrxScript
14{
15
[7645]16#define BEGIN_LUA_CHECK(vm)   lua_State *state = (lua_State *) vm; \
17                              if (vm.isOk ()) {
18#define END_LUA_CHECK         }
19
20
[7653]21  /**
22   * @brief Constructor. Sets up the lua stack and the "this" table
23   *
24   *
25   *
26   */
[7645]27
[7653]28  LuaScript::LuaScript ()
29      : methodCount (0) , argumentCount (0), functionName()
30  {
31    virtualMachine.init();
32    lua_State *state = (lua_State *) virtualMachine;
[7645]33
[7653]34    if (virtualMachine.isOk ())
35    {
[7645]36      // Create a reference to the "this" table. Each reference is unique
[7653]37      lua_newtable (state);
38      thisReference = luaL_ref (state, LUA_REGISTRYINDEX);
[7645]39
40      // Save the "this" table to index 0 of the "this" table
[7653]41      LuaRestoreStack rs (virtualMachine);
42      lua_rawgeti (state, LUA_REGISTRYINDEX, thisReference);
43      lua_pushlightuserdata (state, (void *) this);
44      lua_rawseti (state, -2, 0);
45    }
[7645]46
[7653]47  }
[7645]48
49
[7653]50  /**
51   * @brief Deconstructor
52   *
53   */
[7645]54
[7653]55  LuaScript::~LuaScript (void)
56  {
57    LuaRestoreStack rs (virtualMachine);
[7645]58
[7653]59    BEGIN_LUA_CHECK (virtualMachine)
60    // Get the reference "this" table
61    lua_rawgeti (state, LUA_REGISTRYINDEX, thisReference);
[7645]62
[7653]63    // Clear index 0
64    lua_pushnil (state);
65    lua_rawseti (state, -2, 0);
66    END_LUA_CHECK
[7645]67
[7653]68  }
[7645]69
70
71
[7653]72  /**
73   * @brief Compiles a given buffer. (reads it into the lua stack)
74   * @param pbBuffer buffer to compile
75   * @param size_t length of the buffer
76   *
77   * @return true if it succeeded
78   */
[7645]79
[7653]80  bool LuaScript::compileBuffer (unsigned char *pbBuffer, size_t szLen)
81  {
82    assert (pbBuffer != NULL && "LuaScript::compileBuffer ->  pbBuffer == NULL");
83    assert (szLen != 0 && "LuaScript::compileBuffer -> szLen == 0");
84    assert (virtualMachine.isOk () && "VM Not OK");
[7645]85
[7653]86    // Make sure we have the correct "this" table
87    LuaThis luaThis (virtualMachine, thisReference);
[7645]88
[7653]89    return virtualMachine.runBuffer (pbBuffer, szLen);
90  }
[7645]91
92
[7653]93  /**
94   * @brief Compiles a given file. (reads it into the lua stack)
95   * @param strFilename filename
96   *
97   * @return true if it succeeded
98   */
[7645]99
[7653]100  bool LuaScript::compileFile (const std::string& strFilename)
101  {
102    //assert (strFilename != NULL && "LuaScript::compileFile -> strFilename == NULL");
103    assert (virtualMachine.isOk () && "VM Not OK");
[7645]104
[7653]105    // Make sure we have the correct "this" table
106    LuaThis luaThis (virtualMachine, thisReference);
[7645]107
[7653]108    return virtualMachine.runFile (strFilename);
109  }
[7645]110
111
[7653]112  /**
113   * @brief Registers a function with Lua, the function will be registered in the "this" table
114   * @param strFuncName name of the function by which it goes by in lua
115   *
116   * @return the pseudoindex of the function
117   */
[7645]118
[7653]119  int LuaScript::registerFunction (const std::string& strFuncName)
120  {
121    //  assert (strFuncName != NULL && "LuaScript::registerFunction -> strFuncName == NULL");
122    assert (virtualMachine.isOk () && "VM Not OK");
[7645]123
[7653]124    int iMethodIdx = -1;
[7645]125
[7653]126    LuaRestoreStack rs (virtualMachine);
[7645]127
[7653]128    BEGIN_LUA_CHECK (virtualMachine)
129    iMethodIdx = ++methodCount;
[7645]130
[7653]131    // Register a function with the lua script. Added it to the "this" table
132    lua_rawgeti (state, LUA_REGISTRYINDEX, thisReference);
[7645]133
[7653]134    // Push the function and parameters
135    lua_pushstring (state, strFuncName.c_str());
136    lua_pushnumber (state, (lua_Number) iMethodIdx);
137    lua_pushcclosure (state, luaCallback, 1);
138    lua_settable (state, -3);
[7645]139
[7653]140    END_LUA_CHECK
[7645]141
[7653]142    return iMethodIdx;
143  }
[7645]144
145
[7653]146  /**
147   * @brief Selects a script function to run
148   * @param  strFuncName name of the function to run
149   *
150   * @return true on success
151   */
152  bool LuaScript::selectScriptFunction (const std::string& strFuncName)
153  {
154    //  assert (strFuncName != NULL && "LuaScript::selectScriptFunction -> strFuncName == NULL");
155    assert (virtualMachine.isOk () && "VM Not OK");
[7645]156
[7653]157    bool fSuccess = true;
[7645]158
[7653]159    BEGIN_LUA_CHECK (virtualMachine)
160    // Look up function name
161    lua_rawgeti (state, LUA_REGISTRYINDEX, thisReference);
162    lua_pushstring (state, strFuncName.c_str());
163    lua_rawget (state, -2);
164    lua_remove (state, -2);
[7645]165
[7653]166    // Put the "this" table back
167    lua_rawgeti (state, LUA_REGISTRYINDEX, thisReference);
[7645]168
[7653]169    // Check that we have a valid function
170    if (!lua_isfunction (state, -2))
171    {
172      fSuccess = false;
173      lua_pop (state, 2);
174    }
175    else
176    {
177      argumentCount = 0;
178      functionName = strFuncName;
179    }
180    END_LUA_CHECK
181
182    return fSuccess;
[7645]183  }
[7653]184
185
186  /**
187   * @brief Checks to see if a function exists
188   * @param  functionName  Function name
189   *
190   * @return true if the function exists
191   */
192  bool LuaScript::scriptHasFunction (const std::string& functionName)
[7645]193  {
[7653]194    // printf("entered scriptHasFunction\n");
[7645]195
[7653]196    //  assert (strScriptName != NULL && "LuaScript::scriptHasFunction -> strScriptName == NULL");
197    assert (virtualMachine.isOk () && "VM Not OK");
[7645]198
[7653]199    // printf("assertions passed\n");
[7645]200
[7653]201    LuaRestoreStack rs (virtualMachine);
[7645]202
[7653]203    bool fFoundFunc = false;
[7645]204
[7653]205    BEGIN_LUA_CHECK (virtualMachine)
206    lua_rawgeti (state, LUA_REGISTRYINDEX, thisReference);
207    lua_pushstring (state, functionName.c_str());
208    lua_rawget (state, -2);
209    lua_remove (state, -2);
[7645]210
[7653]211    if (lua_isfunction (state, -1))
212    {
213      fFoundFunc = true;
214    }
215    END_LUA_CHECK
[7645]216
[7653]217    return fFoundFunc;
[7645]218
219  }
220
221
[7653]222  /**
223   * @brief Adds a parameter to the parameter list
224   * @param  string  string to be added as parameter for a function.
225   *
226   */
[7645]227
[7654]228  void LuaScript::addParam (const std::string& string)
[7653]229  {
230    assert (virtualMachine.isOk () && "VM Not OK");
[7645]231
[7654]232    BEGIN_LUA_CHECK (virtualMachine);
233    lua_pushstring (state, string.c_str());
[7653]234    ++argumentCount;
[7654]235    END_LUA_CHECK;
[7653]236  }
[7645]237
238
[7653]239  /**
240   * @brief Adds a parameter to the parameter list
241   * @param  iInt  integer to be added as parameter for a function.
242   *
243   */
[7645]244
[7653]245  void LuaScript::addParam (int iInt)
246  {
247    assert (virtualMachine.isOk () && "VM Not OK");
[7645]248
[7653]249    BEGIN_LUA_CHECK (virtualMachine)
250    lua_pushnumber (state, (lua_Number) iInt);
251    ++argumentCount;
252    END_LUA_CHECK
253  }
[7645]254
255
[7653]256  /**
257   * @brief Adds a parameter to the parameter list
258   * @param  fFloat  float to be added as parameter for a function.
259   *
260   */
261  void LuaScript::addParam (float fFloat)
262  {
263    assert (virtualMachine.isOk () && "VM Not OK");
[7645]264
[7653]265    BEGIN_LUA_CHECK (virtualMachine)
266    lua_pushnumber (state, (lua_Number) fFloat);
267    ++argumentCount;
268    END_LUA_CHECK
269  }
[7645]270
271
[7653]272  /**
273   * @brief Runs the selected script function
274   * @param  nReturns the count of return values
275   *
276   * @return true on success
277   */
278  bool LuaScript::run (int nReturns /* = 0 */)
279  {
280    assert (virtualMachine.isOk () && "VM Not OK");
[7645]281
[7653]282    // At this point there should be a parameters and a function on the
283    // Lua stack. Each function get a "this" parameter as default and is
284    // pushed onto the stack when the method is selected
[7645]285
[7653]286    bool fSuccess = virtualMachine.callFunction (argumentCount + 1, nReturns);
[7645]287
[7653]288    if (fSuccess == true && nReturns > 0)
289    {
290      // Check for returns
291      handleReturns (virtualMachine, functionName);
292      lua_pop ((lua_State *) virtualMachine, nReturns);
293    }
[7645]294
[7653]295    return fSuccess;
[7645]296  }
297
298
[7653]299  /**
300   * @brief This function adds an object to a script so that the object is accessable from within the luascript.
301   *
302   * @param scriptable the scriptable object to add.
303   * @param strObjName the name that the object goes by in the script.
304   * @param luaScript  the script to which the scrtiptable is added
305   *
306   * @return a lua reference to the added object
307   *
308   *
309   *
310   */
[7645]311
[7653]312  int LuaScript::addScriptableToScript(Scriptable* scriptable, const std::string& strObjName)
313  {
[7645]314
[7653]315    lua_State *state = (lua_State *) (this->virtualMachine);
[7645]316
[7653]317    if(strObjName.compare(std::string("this")) != 0)
[7645]318    {
[7653]319      if (virtualMachine.isOk ())
320      {
321        /*create object table*/
322        // Create a reference to the "object" table and set a name for the reference. Each reference is unique
[7645]323
[7653]324        lua_newtable (state);
325        int  objRef = luaL_ref (state, LUA_REGISTRYINDEX);
326        lua_rawgeti (state, LUA_REGISTRYINDEX, objRef);
327        lua_setglobal (state, strObjName.c_str());
[7645]328
329
[7653]330        // Save the "object" table to index 0 of the "object" table
331        LuaRestoreStack rs(virtualMachine);
332        lua_rawgeti (state, LUA_REGISTRYINDEX, objRef);
333        lua_pushlightuserdata (state, scriptable);
334        lua_rawseti (state, -2, 0);
[7645]335
[7653]336        if(! addScriptableToList(scriptable,objRef))
337          std::cout<<"scriptable not added"<<std::endl;
338        if(!(scriptable->scriptableAdded(this,thisReference,objRef)))
339          std::cout<<"scriptableAdded returned false"<<std::endl;
[7645]340
[7653]341        return objRef;
342      }
[7645]343    }
344
[7653]345    return -1;
[7645]346
[7653]347  }
[7645]348
349
350
[7653]351  /**
352   * @brief Add the function to a scriptable in the Script
353   * @param strFuncName name of the function by which it goes by in lua
354   * @param toScriptable reference to the scriptable the function should be associated with
355   * @param methodIndex index of the last function.
356   *
357   * @return the pseudoindex of the function, -1 on failure
358   */
[7645]359
[7653]360  int LuaScript::addFunctionToScriptable(const std::string& strFuncName, int toScriptable, int lastMethodIndex)
361  {
362    //  assert (strFuncName != NULL && "LuaScript::registerFunction -> strFuncName == NULL");
363    assert (virtualMachine.isOk () && "VM Not OK");
[7645]364
365
[7653]366    //get the last method index from the Script
367    Scriptable* scriptable = getScriptableByReference(toScriptable);
368    int iMethodIdx = -1;
[7645]369
[7653]370    if(scriptable)
371    {
372      LuaRestoreStack rs (virtualMachine);
[7645]373
[7653]374      BEGIN_LUA_CHECK (virtualMachine)
375      // Register a function with the lua script. Added it to the "toScrtiptable" table
376      lua_rawgeti (state, LUA_REGISTRYINDEX, toScriptable);
[7645]377
[7653]378      if (lua_istable (state, 1))
379      {
380        iMethodIdx = ++lastMethodIndex;
[7645]381
[7653]382        // Push the function and parameters
383        lua_pushstring (state, strFuncName.c_str());
384        lua_pushnumber (state, (lua_Number) iMethodIdx);
385        lua_pushcclosure (state, luaCallback, 1);
386        lua_settable (state, -3);
387      }
388      END_LUA_CHECK
[7645]389
[7653]390    }
391    return iMethodIdx;
[7645]392  }
393
394
[7653]395  Scriptable* LuaScript::getScriptableByReference(int scrptblRef)
396  {
[7645]397
[7653]398    bool notFound = true;
[7645]399    std::list<Scrptbl>::iterator it = scriptableList.begin();
400
401    while(notFound && it != scriptableList.end() )
402    {
403      if((*it).scriptableRef == scrptblRef)
404      {
405        notFound = false;
406        return (*it).scriptable;
407      }
408      it++;
409    }
410
411
412    if(notFound)
[7653]413      return NULL;
[7645]414
[7653]415  }
[7645]416
[7653]417  int LuaScript::getReferenceByScriptable(Scriptable* scrptbl)
418  {
419    bool notFound = true;
[7645]420
421    std::list<Scrptbl>::iterator it = scriptableList.begin();
422
423    while(notFound && it != scriptableList.end() )
424    {
425      if((*it).scriptable == scrptbl)
426      {
427        notFound = false;
428        return (*it).scriptableRef;
429      }
430      it++;
[7653]431    }
432    if(notFound)
433      return -1;
434  }
[7645]435
[7653]436  bool LuaScript::addScriptableToList(Scriptable* scrptbl, int scriptableRef)
[7645]437  {
[7653]438    if(scrptbl)
[7645]439    {
[7653]440      if(getReferenceByScriptable(scrptbl) == -1) // Script isn't there yet
441      {
442        Scrptbl scriptableTmp;
443        scriptableTmp.scriptable = scrptbl;
444        scriptableTmp.scriptableRef = scriptableRef;
445        scriptableList.push_back(scriptableTmp);
446        return true;
447      }
[7645]448    }
449
[7653]450    return false;
[7645]451
[7653]452  }
[7645]453
[7653]454  bool LuaScript::removeScriptableFromList(Scriptable* toRemove)
[7645]455  {
[7653]456    if(toRemove)
[7645]457    {
[7653]458      int scrptbl = getReferenceByScriptable(toRemove);
[7645]459
[7653]460      if(scrptbl != -1)// if the scriptable is on the list
[7645]461      {
[7653]462        std::list<Scrptbl>::iterator it = scriptableList.begin();
[7645]463
[7653]464        while((*it).scriptable != toRemove && it != scriptableList.end() )
465        {
466          it++;
467        }
468
469        if(it != scriptableList.end())
470        {
471          scriptableList.erase(it);
472          return true;
473        }
[7645]474      }
475    }
[7653]476    return false;
[7645]477  }
478
[7653]479  bool LuaScript::removeScriptableFromList(int scriptable)
480  {
481    return removeScriptableFromList(getScriptableByReference(scriptable));
482  }
[7645]483
484
[7653]485  char LuaScript::whatIsThis()
486  {
487    char result = 'l';
488    return result;
489  }
[7645]490}
491
Note: See TracBrowser for help on using the repository browser.