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
Line 
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
11namespace OrxScript
12{
13
14#define BEGIN_LUA_CHECK(vm)   lua_State *state = (lua_State *) vm; \
15                              if (vm.isOk ()) {
16#define END_LUA_CHECK         }
17
18
19  /**
20   * @brief Constructor. Sets up the lua stack and the "this" table
21   *
22   *
23   *
24   */
25
26  LuaScript::LuaScript ()
27      : methodCount (0) , argumentCount (0), functionName()
28  {
29    virtualMachine.init();
30    lua_State *state = (lua_State *) virtualMachine;
31
32    if (virtualMachine.isOk ())
33    {
34      // Create a reference to the "this" table. Each reference is unique
35      lua_newtable (state);
36      thisReference = luaL_ref (state, LUA_REGISTRYINDEX);
37
38      // Save the "this" table to index 0 of the "this" table
39      LuaRestoreStack rs (virtualMachine);
40      lua_rawgeti (state, LUA_REGISTRYINDEX, thisReference);
41      lua_pushlightuserdata (state, (void *) this);
42      lua_rawseti (state, -2, 0);
43    }
44
45  }
46
47
48  /**
49   * @brief Deconstructor
50   *
51   */
52
53  LuaScript::~LuaScript (void)
54  {
55    LuaRestoreStack rs (virtualMachine);
56
57    BEGIN_LUA_CHECK (virtualMachine)
58    // Get the reference "this" table
59    lua_rawgeti (state, LUA_REGISTRYINDEX, thisReference);
60
61    // Clear index 0
62    lua_pushnil (state);
63    lua_rawseti (state, -2, 0);
64    END_LUA_CHECK
65
66  }
67
68
69
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   */
77
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");
83
84    // Make sure we have the correct "this" table
85    LuaThis luaThis (virtualMachine, thisReference);
86
87    return virtualMachine.runBuffer (pbBuffer, szLen);
88  }
89
90
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   */
97
98  bool LuaScript::compileFile (const std::string& strFilename)
99  {
100    //assert (strFilename != NULL && "LuaScript::compileFile -> strFilename == NULL");
101    assert (virtualMachine.isOk () && "VM Not OK");
102
103    // Make sure we have the correct "this" table
104    LuaThis luaThis (virtualMachine, thisReference);
105
106    return virtualMachine.runFile (strFilename);
107  }
108
109
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   */
116
117  int LuaScript::registerFunction (const std::string& strFuncName)
118  {
119    //  assert (strFuncName != NULL && "LuaScript::registerFunction -> strFuncName == NULL");
120    assert (virtualMachine.isOk () && "VM Not OK");
121
122    int iMethodIdx = -1;
123
124    LuaRestoreStack rs (virtualMachine);
125
126    BEGIN_LUA_CHECK (virtualMachine)
127    iMethodIdx = ++methodCount;
128
129    // Register a function with the lua script. Added it to the "this" table
130    lua_rawgeti (state, LUA_REGISTRYINDEX, thisReference);
131
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);
137
138    END_LUA_CHECK
139
140    return iMethodIdx;
141  }
142
143
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");
154
155    bool fSuccess = true;
156
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);
163
164    // Put the "this" table back
165    lua_rawgeti (state, LUA_REGISTRYINDEX, thisReference);
166
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;
181  }
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)
191  {
192    // printf("entered scriptHasFunction\n");
193
194    //  assert (strScriptName != NULL && "LuaScript::scriptHasFunction -> strScriptName == NULL");
195    assert (virtualMachine.isOk () && "VM Not OK");
196
197    // printf("assertions passed\n");
198
199    LuaRestoreStack rs (virtualMachine);
200
201    bool fFoundFunc = false;
202
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);
208
209    if (lua_isfunction (state, -1))
210    {
211      fFoundFunc = true;
212    }
213    END_LUA_CHECK
214
215    return fFoundFunc;
216
217  }
218
219
220  /**
221   * @brief Adds a parameter to the parameter list
222   * @param  string  string to be added as parameter for a function.
223   *
224   */
225
226  void LuaScript::addParam (char *string)
227  {
228    assert (string != NULL && "LuaScript::addParam -> string == NULL");
229    assert (virtualMachine.isOk () && "VM Not OK");
230
231    BEGIN_LUA_CHECK (virtualMachine)
232    lua_pushstring (state, string);
233    ++argumentCount;
234    END_LUA_CHECK
235  }
236
237
238  /**
239   * @brief Adds a parameter to the parameter list
240   * @param  iInt  integer to be added as parameter for a function.
241   *
242   */
243
244  void LuaScript::addParam (int iInt)
245  {
246    assert (virtualMachine.isOk () && "VM Not OK");
247
248    BEGIN_LUA_CHECK (virtualMachine)
249    lua_pushnumber (state, (lua_Number) iInt);
250    ++argumentCount;
251    END_LUA_CHECK
252  }
253
254
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");
263
264    BEGIN_LUA_CHECK (virtualMachine)
265    lua_pushnumber (state, (lua_Number) fFloat);
266    ++argumentCount;
267    END_LUA_CHECK
268  }
269
270
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");
280
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
284
285    bool fSuccess = virtualMachine.callFunction (argumentCount + 1, nReturns);
286
287    if (fSuccess == true && nReturns > 0)
288    {
289      // Check for returns
290      handleReturns (virtualMachine, functionName);
291      lua_pop ((lua_State *) virtualMachine, nReturns);
292    }
293
294    return fSuccess;
295  }
296
297
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   */
310
311  int LuaScript::addScriptableToScript(Scriptable* scriptable, const std::string& strObjName)
312  {
313
314    lua_State *state = (lua_State *) (this->virtualMachine);
315
316    if(strObjName.compare(std::string("this")) != 0)
317    {
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
322
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());
327
328
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);
334
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;
339
340        return objRef;
341      }
342    }
343
344    return -1;
345
346  }
347
348
349
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   */
358
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");
363
364
365    //get the last method index from the Script
366    Scriptable* scriptable = getScriptableByReference(toScriptable);
367    int iMethodIdx = -1;
368
369    if(scriptable)
370    {
371      LuaRestoreStack rs (virtualMachine);
372
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);
376
377      if (lua_istable (state, 1))
378      {
379        iMethodIdx = ++lastMethodIndex;
380
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
388
389    }
390    return iMethodIdx;
391  }
392
393
394  Scriptable* LuaScript::getScriptableByReference(int scrptblRef)
395  {
396
397    bool notFound = true;
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)
412      return NULL;
413
414  }
415
416  int LuaScript::getReferenceByScriptable(Scriptable* scrptbl)
417  {
418    bool notFound = true;
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++;
430    }
431    if(notFound)
432      return -1;
433  }
434
435  bool LuaScript::addScriptableToList(Scriptable* scrptbl, int scriptableRef)
436  {
437    if(scrptbl)
438    {
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      }
447    }
448
449    return false;
450
451  }
452
453  bool LuaScript::removeScriptableFromList(Scriptable* toRemove)
454  {
455    if(toRemove)
456    {
457      int scrptbl = getReferenceByScriptable(toRemove);
458
459      if(scrptbl != -1)// if the scriptable is on the list
460      {
461        std::list<Scrptbl>::iterator it = scriptableList.begin();
462
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        }
473      }
474    }
475    return false;
476  }
477
478  bool LuaScript::removeScriptableFromList(int scriptable)
479  {
480    return removeScriptableFromList(getScriptableByReference(scriptable));
481  }
482
483
484  char LuaScript::whatIsThis()
485  {
486    char result = 'l';
487    return result;
488  }
489}
490
Note: See TracBrowser for help on using the repository browser.