Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

merged the scriptengine back to the trunk

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