Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

added script_engine

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