Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/script_engine/src/lib/script_engine/Script.cc @ 7653

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

orxonox/script_engine: namespace OrxScript introduced

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