1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2013 Robert Osfield
2  *
3  * This library is open source and may be redistributed and/or modified under
4  * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5  * (at your option) any later version.  The full license is in LICENSE file
6  * included with this distribution, and on the openscenegraph.org website.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * OpenSceneGraph Public License for more details.
12 */
13 
14 #include "LuaScriptEngine.h"
15 
16 #include <osg/io_utils>
17 #include <osg/observer_ptr>
18 #include <osgDB/ReadFile>
19 #include <osgDB/WriteFile>
20 
21 using namespace lua;
22 
23 
24 
25 
26 class LuaCallbackObject : public osg::CallbackObject
27 {
28 public:
LuaCallbackObject(const std::string & methodName,const LuaScriptEngine * lse,int ref)29     LuaCallbackObject(const std::string& methodName, const LuaScriptEngine* lse, int ref):_lse(lse),_ref(ref)
30     {
31         setName(methodName);
32     }
33 
run(osg::Object * object,osg::Parameters & inputParameters,osg::Parameters & outputParameters) const34     virtual bool run(osg::Object* object, osg::Parameters& inputParameters, osg::Parameters& outputParameters) const
35     {
36         if (!_lse)
37         {
38             OSG_NOTICE << "Warning: Ignoring call to Lua by an expired callback" << std::endl;
39             return false;
40         }
41 
42         // a strong reference is necessary as the lua call might trigger deletion of the LuaScriptEngine object
43         // avoid overhead by observer_ptr<>::lock as a race on run/destruction never is valid
44         osg::ref_ptr<const LuaScriptEngine> lse(_lse.get());
45 
46         int topBeforeCall = lua_gettop(lse->getLuaState());
47 
48         lua_rawgeti(lse->getLuaState(), LUA_REGISTRYINDEX, _ref);
49 
50         int numInputs = 1;
51         lse->pushParameter(object);
52 
53         for(osg::Parameters::iterator itr = inputParameters.begin();
54             itr != inputParameters.end();
55             ++itr)
56         {
57             lse->pushParameter(itr->get());
58             ++numInputs;
59         }
60 
61         if (lua_pcall(lse->getLuaState(), numInputs, LUA_MULTRET,0)!=0)
62         {
63             OSG_NOTICE<<"Lua error : "<<lua_tostring(lse->getLuaState(), -1)<<std::endl;
64             return false;
65         }
66 
67         int topAfterCall = lua_gettop(lse->getLuaState());
68         int numReturns = topAfterCall-topBeforeCall;
69         for(int i=1; i<=numReturns; ++i)
70         {
71             outputParameters.insert(outputParameters.begin(), lse->popParameterObject());
72         }
73         return true;
74     }
75 
getRef() const76     int getRef() const { return _ref; }
77 
78 protected:
79 
80     osg::observer_ptr<const LuaScriptEngine> _lse;
81     int _ref;
82 };
83 
84 
getProperty(lua_State * _lua)85 static int getProperty(lua_State * _lua)
86 {
87     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
88 
89     int n = lua_gettop(_lua);    /* number of arguments */
90     if (n==2 && lua_type(_lua, 1)==LUA_TTABLE)
91     {
92         if (lua_type(_lua, 2)==LUA_TSTRING)
93         {
94             std::string propertyName = lua_tostring(_lua, 2);
95             osg::Object* object  = lse->getObjectFromTable<osg::Object>(1);
96 
97             return lse->pushPropertyToStack(object, propertyName);
98         }
99     }
100 
101     OSG_NOTICE<<"Warning: Lua getProperty() not matched"<<std::endl;
102     return 0;
103 }
104 
105 
setProperty(lua_State * _lua)106 static int setProperty(lua_State* _lua)
107 {
108     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
109 
110     int n = lua_gettop(_lua);    /* number of arguments */
111     if (n==3 && lua_type(_lua, 1)==LUA_TTABLE)
112     {
113         if (lua_type(_lua, 2)==LUA_TSTRING)
114         {
115             std::string propertyName = lua_tostring(_lua, 2);
116             osg::Object* object  = lse->getObjectFromTable<osg::Object>(1);
117 
118             return lse->setPropertyFromStack(object, propertyName);
119         }
120     }
121 
122     OSG_NOTICE<<"Warning: Lua setProperty() not matched"<<std::endl;
123     return 0;
124 }
125 
126 //////////////////////////////////////////////////////////////////////////////////////
127 //
128 //  Vector container support
129 //
getContainerProperty(lua_State * _lua)130 static int getContainerProperty(lua_State * _lua)
131 {
132     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
133 
134     int n = lua_gettop(_lua);    /* number of arguments */
135     if (n==2 && lua_type(_lua, 1)==LUA_TTABLE)
136     {
137         if (lua_type(_lua, 2)==LUA_TSTRING)
138         {
139             std::string propertyName = lua_tostring(_lua, 2);
140             osg::Object* object  = lse->getObjectFromTable<osg::Object>(1);
141             std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName");
142 
143             return lse->pushPropertyToStack(object, propertyName);
144         }
145         else if (lua_type(_lua, 2)==LUA_TNUMBER)
146         {
147             double index = lua_tonumber(_lua, 2);
148             const osg::Object* object  = lse->getObjectFromTable<osg::Object>(1);
149             std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName");
150 
151             // check to see if Object "is a" vector
152             osgDB::BaseSerializer::Type type;
153             osgDB::BaseSerializer* bs = lse->getClassInterface().getSerializer(object, containerPropertyName, type);
154             osgDB::VectorBaseSerializer* vs = dynamic_cast<osgDB::VectorBaseSerializer*>(bs);
155             if (vs)
156             {
157                 const void* dataPtr = vs->getElement(*object, (unsigned int) index);
158                 if (dataPtr)
159                 {
160                     SerializerScratchPad valuesp(vs->getElementType(), dataPtr, vs->getElementSize());
161                     return lse->pushDataToStack(&valuesp);
162                 }
163                 else
164                 {
165                     lua_pushnil(_lua);
166                     return 1;
167                 }
168             }
169         }
170     }
171 
172     OSG_NOTICE<<"Warning: Lua getContainerProperty() not matched"<<std::endl;
173     return 0;
174 }
175 
176 
setContainerProperty(lua_State * _lua)177 static int setContainerProperty(lua_State* _lua)
178 {
179     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
180 
181     int n = lua_gettop(_lua);    /* number of arguments */
182     if (n==3 && lua_type(_lua, 1)==LUA_TTABLE)
183     {
184         if (lua_type(_lua, 2)==LUA_TSTRING)
185         {
186             std::string propertyName = lua_tostring(_lua, 2);
187             osg::Object* object  = lse->getObjectFromTable<osg::Object>(1);
188             std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName");
189 
190             return lse->setPropertyFromStack(object, propertyName);
191         }
192         else if (lua_type(_lua, 2)==LUA_TNUMBER)
193         {
194             double index = lua_tonumber(_lua, 2);
195 
196             osg::Object* object  = lse->getObjectFromTable<osg::Object>(1);
197             std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName");
198 
199             // check to see if Object "is a" vector
200             osgDB::BaseSerializer::Type type;
201             osgDB::BaseSerializer* bs = lse->getClassInterface().getSerializer(object, containerPropertyName, type);
202             osgDB::VectorBaseSerializer* vs = dynamic_cast<osgDB::VectorBaseSerializer*>(bs);
203             if (vs)
204             {
205                 SerializerScratchPad ssp;
206                 lse->getDataFromStack(&ssp, vs->getElementType(), 3);
207                 {
208                     vs->setElement(*object, (unsigned int) index, ssp.data);
209                 }
210             }
211             return 0;
212         }
213     }
214 
215     OSG_NOTICE<<"Warning: Lua setContainerProperty() not matched"<<std::endl;
216     return 0;
217 }
218 
getContainerSize(lua_State * _lua)219 static int getContainerSize(lua_State* _lua)
220 {
221     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
222     int n = lua_gettop(_lua);    /* number of arguments */
223     if (n<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0;
224 
225     osg::Object* object  = lse->getObjectFromTable<osg::Object>(1);
226     std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName");
227 
228     // check to see if Object "is a" vector
229     osgDB::BaseSerializer::Type type;
230     osgDB::BaseSerializer* bs = lse->getClassInterface().getSerializer(object, containerPropertyName, type);
231     osgDB::VectorBaseSerializer* vs = dynamic_cast<osgDB::VectorBaseSerializer*>(bs);
232     if (vs)
233     {
234         lua_pushinteger(lse->getLuaState(), vs->size(*object));
235         return 1;
236     }
237 
238     return 0;
239 }
240 
callVectorClear(lua_State * _lua)241 static int callVectorClear(lua_State* _lua)
242 {
243     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
244     int n = lua_gettop(_lua);    /* number of arguments */
245     if (n<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0;
246 
247     osg::Object* object  = lse->getObjectFromTable<osg::Object>(1);
248     std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName");
249 
250     // check to see if Object "is a" vector
251     osgDB::BaseSerializer::Type type;
252     osgDB::BaseSerializer* bs = lse->getClassInterface().getSerializer(object, containerPropertyName, type);
253     osgDB::VectorBaseSerializer* vs = dynamic_cast<osgDB::VectorBaseSerializer*>(bs);
254     if (vs)
255     {
256         vs->clear(*object);
257         return 0;
258     }
259 
260     return 0;
261 }
262 
callVectorResize(lua_State * _lua)263 static int callVectorResize(lua_State* _lua)
264 {
265     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
266     int n = lua_gettop(_lua);    /* number of arguments */
267     if (n<2 || lua_type(_lua, 1)!=LUA_TTABLE || lua_type(_lua, 2)!=LUA_TNUMBER) return 0;
268 
269     double numElements = lua_tonumber(lse->getLuaState(),2);
270     osg::Object* object  = lse->getObjectFromTable<osg::Object>(1);
271     std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName");
272 
273     // check to see if Object "is a" vector
274     osgDB::BaseSerializer::Type type;
275     osgDB::BaseSerializer* bs = lse->getClassInterface().getSerializer(object, containerPropertyName, type);
276     osgDB::VectorBaseSerializer* vs = dynamic_cast<osgDB::VectorBaseSerializer*>(bs);
277     if (vs)
278     {
279         vs->resize(*object, static_cast<unsigned int>(numElements));
280     }
281 
282     return 0;
283 }
284 
callVectorReserve(lua_State * _lua)285 static int callVectorReserve(lua_State* _lua)
286 {
287     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
288     int n = lua_gettop(_lua);    /* number of arguments */
289     if (n<2 || lua_type(_lua, 1)!=LUA_TTABLE || lua_type(_lua, 2)!=LUA_TNUMBER) return 0;
290 
291     double numElements = lua_tonumber(lse->getLuaState(),2);
292     osg::Object* object  = lse->getObjectFromTable<osg::Object>(1);
293     std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName");
294 
295     // check to see if Object "is a" vector
296     osgDB::BaseSerializer::Type type;
297     osgDB::BaseSerializer* bs = lse->getClassInterface().getSerializer(object, containerPropertyName, type);
298     osgDB::VectorBaseSerializer* vs = dynamic_cast<osgDB::VectorBaseSerializer*>(bs);
299     if (vs)
300     {
301         vs->reserve(*object, static_cast<unsigned int>(numElements));
302     }
303 
304     return 0;
305 }
306 
307 
callVectorAdd(lua_State * _lua)308 static int callVectorAdd(lua_State* _lua)
309 {
310     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
311     int n = lua_gettop(_lua);    /* number of arguments */
312     if (n<2 || lua_type(_lua, 1)!=LUA_TTABLE) return 0;
313 
314     osg::Object* object  = lse->getObjectFromTable<osg::Object>(1);
315     std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName");
316 
317     // check to see if Object "is a" vector
318     osgDB::BaseSerializer::Type type;
319     osgDB::BaseSerializer* bs = lse->getClassInterface().getSerializer(object, containerPropertyName, type);
320     osgDB::VectorBaseSerializer* vs = dynamic_cast<osgDB::VectorBaseSerializer*>(bs);
321     if (vs)
322     {
323         SerializerScratchPad ssp;
324         lse->getDataFromStack(&ssp, vs->getElementType(), 2);
325 
326         if (ssp.dataType==vs->getElementType())
327         {
328             vs->addElement(*object, ssp.data);
329         }
330         else
331         {
332             OSG_NOTICE<<"Failed to match table type"<<std::endl;
333         }
334 
335     }
336 
337     return 0;
338 }
339 
340 //////////////////////////////////////////////////////////////////////////////////////
341 //
342 //  Map container support
343 //
getMapProperty(lua_State * _lua)344 static int getMapProperty(lua_State * _lua)
345 {
346     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
347 
348     int n = lua_gettop(_lua);    /* number of arguments */
349     if (n==2 && lua_type(_lua, 1)==LUA_TTABLE)
350     {
351         if (lua_type(_lua, 2)==LUA_TSTRING)
352         {
353             std::string propertyName = lua_tostring(_lua, 2);
354             osg::Object* object  = lse->getObjectFromTable<osg::Object>(1);
355             std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName");
356 
357             return lse->pushPropertyToStack(object, propertyName);
358         }
359         else
360         {
361             const osg::Object* object  = lse->getObjectFromTable<osg::Object>(1);
362             std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName");
363 
364             // check to see if Object "is a" vector
365             osgDB::BaseSerializer::Type type;
366             osgDB::BaseSerializer* bs = lse->getClassInterface().getSerializer(object, containerPropertyName, type);
367             osgDB::MapBaseSerializer* ms = dynamic_cast<osgDB::MapBaseSerializer*>(bs);
368 
369             if (ms)
370             {
371                 SerializerScratchPad keysp;
372                 lse->getDataFromStack(&keysp, ms->getKeyType(),2);
373                 if (keysp.dataType==ms->getKeyType())
374                 {
375                     const void* dataPtr = ms->getElement(*object, keysp.data);
376                     if (dataPtr)
377                     {
378                         SerializerScratchPad valuesp(ms->getElementType(), dataPtr, ms->getElementSize());
379                         return lse->pushDataToStack(&valuesp);
380                     }
381                     else
382                     {
383                         lua_pushnil(_lua);
384                         return 1;
385                     }
386 
387                    return 0;
388                 }
389             }
390         }
391     }
392 
393     OSG_NOTICE<<"Warning: Lua getMapProperty() not matched"<<std::endl;
394     return 0;
395 }
396 
397 
setMapProperty(lua_State * _lua)398 static int setMapProperty(lua_State* _lua)
399 {
400     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
401 
402     int n = lua_gettop(_lua);    /* number of arguments */
403 
404     if (n==3 && lua_type(_lua, 1)==LUA_TTABLE)
405     {
406         if (lua_type(_lua, 2)==LUA_TSTRING)
407         {
408             std::string propertyName = lua_tostring(_lua, 2);
409             osg::Object* object  = lse->getObjectFromTable<osg::Object>(1);
410             std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName");
411 
412             return lse->setPropertyFromStack(object, propertyName);
413         }
414         else
415         {
416             osg::Object* object  = lse->getObjectFromTable<osg::Object>(1);
417             std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName");
418 
419             // check to see if Object "is a" vector
420             osgDB::BaseSerializer::Type type;
421             osgDB::BaseSerializer* bs = lse->getClassInterface().getSerializer(object, containerPropertyName, type);
422             osgDB::MapBaseSerializer* ms = dynamic_cast<osgDB::MapBaseSerializer*>(bs);
423 
424             if (ms)
425             {
426                 SerializerScratchPad keysp, valuesp;
427                 lse->getDataFromStack(&keysp, ms->getKeyType(),2);
428                 lse->getDataFromStack(&valuesp, ms->getElementType(),3);
429                 if (keysp.dataType==ms->getKeyType() && ms->getElementType()==valuesp.dataType)
430                 {
431                     ms->setElement(*object, keysp.data, valuesp.data);
432                     return 0;
433                 }
434                 else
435                 {
436                     OSG_NOTICE<<"Warning: Lua setMapProperty() : Failed to matched map element "<<std::endl;
437                     OSG_NOTICE<<"                                keysp.dataType="<<keysp.dataType<<std::endl;
438                     OSG_NOTICE<<"                                valuesp.dataType="<<valuesp.dataType<<std::endl;
439                     return 0;
440                 }
441 
442             }
443         }
444     }
445 
446     OSG_NOTICE<<"Warning: Lua setMapProperty() not matched"<<std::endl;
447     return 0;
448 }
449 
callMapClear(lua_State * _lua)450 static int callMapClear(lua_State* _lua)
451 {
452     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
453     int n = lua_gettop(_lua);    /* number of arguments */
454     if (n<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0;
455 
456     osg::Object* object  = lse->getObjectFromTable<osg::Object>(1);
457     std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName");
458 
459     // check to see if Object "is a" vector
460     osgDB::BaseSerializer::Type type;
461     osgDB::BaseSerializer* bs = lse->getClassInterface().getSerializer(object, containerPropertyName, type);
462     osgDB::MapBaseSerializer* ms = dynamic_cast<osgDB::MapBaseSerializer*>(bs);
463     if (ms)
464     {
465         ms->clear(*object);
466         return 0;
467     }
468 
469     return 0;
470 }
471 
getMapSize(lua_State * _lua)472 static int getMapSize(lua_State* _lua)
473 {
474     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
475     int n = lua_gettop(_lua);    /* number of arguments */
476     if (n<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0;
477 
478     osg::Object* object  = lse->getObjectFromTable<osg::Object>(1);
479     std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName");
480 
481     // check to see if Object "is a" vector
482     osgDB::BaseSerializer::Type type;
483     osgDB::BaseSerializer* bs = lse->getClassInterface().getSerializer(object, containerPropertyName, type);
484     osgDB::MapBaseSerializer* ms = dynamic_cast<osgDB::MapBaseSerializer*>(bs);
485     if (ms)
486     {
487         lua_pushinteger(lse->getLuaState(), ms->size(*object));
488         return 1;
489     }
490 
491     return 0;
492 }
493 
494 
createMapIterator(lua_State * _lua)495 static int createMapIterator(lua_State* _lua)
496 {
497     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
498     int n = lua_gettop(_lua);    /* number of arguments */
499     if (n<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0;
500 
501     osg::Object* object  = lse->getObjectFromTable<osg::Object>(1);
502     std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName");
503 
504     // check to see if Object "is a" vector
505     osgDB::BaseSerializer::Type type;
506     osgDB::BaseSerializer* bs = lse->getClassInterface().getSerializer(object, containerPropertyName, type);
507     osgDB::MapBaseSerializer* ms = dynamic_cast<osgDB::MapBaseSerializer*>(bs);
508     if (ms)
509     {
510         lse->pushObject(ms->createIterator(*object));
511         return 1;
512     }
513 
514     return 0;
515 }
516 
createMapReverseIterator(lua_State * _lua)517 static int createMapReverseIterator(lua_State* _lua)
518 {
519     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
520     int n = lua_gettop(_lua);    /* number of arguments */
521     if (n<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0;
522 
523     osg::Object* object  = lse->getObjectFromTable<osg::Object>(1);
524     std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName");
525 
526     // check to see if Object "is a" vector
527     osgDB::BaseSerializer::Type type;
528     osgDB::BaseSerializer* bs = lse->getClassInterface().getSerializer(object, containerPropertyName, type);
529     osgDB::MapBaseSerializer* ms = dynamic_cast<osgDB::MapBaseSerializer*>(bs);
530     if (ms)
531     {
532         lse->pushObject(ms->createReverseIterator(*object));
533         return 1;
534     }
535 
536     return 0;
537 }
538 
539 //////////////////////////////////////////////////////////////////////////////////////
540 //
541 //  MapIteratorObject support
542 //
callMapIteratorAdvance(lua_State * _lua)543 static int callMapIteratorAdvance(lua_State* _lua)
544 {
545     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
546     if (lua_gettop(_lua)<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0;
547     osgDB::MapIteratorObject* mio  = lse->getObjectFromTable<osgDB::MapIteratorObject>(1);
548     if (mio)
549     {
550         lua_pushboolean(lse->getLuaState(), mio->advance());
551         return 1;
552     }
553 
554     return 0;
555 }
556 
callMapIteratorValid(lua_State * _lua)557 static int callMapIteratorValid(lua_State* _lua)
558 {
559     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
560     if (lua_gettop(_lua)<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0;
561     osgDB::MapIteratorObject* mio  = lse->getObjectFromTable<osgDB::MapIteratorObject>(1);
562     if (mio)
563     {
564         lua_pushboolean(lse->getLuaState(), mio->valid());
565         return 1;
566     }
567 
568     return 0;
569 }
570 
getMapIteratorKey(lua_State * _lua)571 static int getMapIteratorKey(lua_State* _lua)
572 {
573     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
574     if (lua_gettop(_lua)<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0;
575     osgDB::MapIteratorObject* mio  = lse->getObjectFromTable<osgDB::MapIteratorObject>(1);
576     if (mio)
577     {
578         const void* dataPtr = mio->getKey();
579         if (dataPtr)
580         {
581             SerializerScratchPad valuesp(mio->getKeyType(), dataPtr, mio->getKeySize());
582             return lse->pushDataToStack(&valuesp);
583         }
584         else
585         {
586             lua_pushnil(_lua);
587             return 1;
588         }
589     }
590 
591     return 0;
592 }
593 
getMapIteratorElement(lua_State * _lua)594 static int getMapIteratorElement(lua_State* _lua)
595 {
596     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
597     if (lua_gettop(_lua)<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0;
598     osgDB::MapIteratorObject* mio  = lse->getObjectFromTable<osgDB::MapIteratorObject>(1);
599     if (mio)
600     {
601         const void* dataPtr = mio->getElement();
602         if (dataPtr)
603         {
604             SerializerScratchPad valuesp(mio->getElementType(), dataPtr, mio->getElementSize());
605             return lse->pushDataToStack(&valuesp);
606         }
607         else
608         {
609             lua_pushnil(_lua);
610             return 1;
611         }
612     }
613     OSG_NOTICE<<"getMapIteratorElement failed. "<<std::endl;
614     return 0;
615 }
616 
617 
setMapIteratorElement(lua_State * _lua)618 static int setMapIteratorElement(lua_State* _lua)
619 {
620     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
621     if (lua_gettop(_lua)<2 || lua_type(_lua, 1)!=LUA_TTABLE) return 0;
622     osgDB::MapIteratorObject* mio  = lse->getObjectFromTable<osgDB::MapIteratorObject>(1);
623     if (mio)
624     {
625         SerializerScratchPad valuesp;
626         lse->getDataFromStack(&valuesp, mio->getElementType(), 2);
627 
628         if (mio->getElementType()==valuesp.dataType)
629         {
630             mio->setElement(valuesp.data);
631             return 0;
632         }
633         else
634         {
635             OSG_NOTICE<<"Warning: Lua setMapIteratorElement() : Failed to matched map element type, valuesp.dataType="<<valuesp.dataType<<std::endl;
636             return 0;
637         }
638     }
639 
640     return 0;
641 }
642 
643 
644 //////////////////////////////////////////////////////////////////////////////////////
645 //
646 //  StateSet support
647 //
convertStringToStateAttributeValue(const std::string & valueString,osg::StateAttribute::OverrideValue defaultValue,bool & setOnOff)648 static int convertStringToStateAttributeValue(const std::string& valueString, osg::StateAttribute::OverrideValue defaultValue, bool& setOnOff)
649 {
650     osg::StateAttribute::OverrideValue value=defaultValue;
651 
652     if (valueString.find("ON")!=std::string::npos) { value = osg::StateAttribute::ON; setOnOff = true; }
653     if (valueString.find("OFF")!=std::string::npos) { value = osg::StateAttribute::OFF; setOnOff = true; }
654 
655     if (valueString.find("OVERRIDE")!=std::string::npos) value = value | osg::StateAttribute::OVERRIDE;
656     if (valueString.find("PROTECTED")!=std::string::npos) value = value | osg::StateAttribute::PROTECTED;
657     if (valueString.find("INHERIT")!=std::string::npos) value = value | osg::StateAttribute::INHERIT;
658     return value;
659 }
660 
convertStateAttributeValueToString(unsigned int value,bool withOnOffCheck)661 static std::string convertStateAttributeValueToString(unsigned int value, bool withOnOffCheck)
662 {
663     std::string valueString;
664     if (withOnOffCheck)
665     {
666         if ((value&osg::StateAttribute::ON)!=0) { if (!valueString.empty()) valueString.append(", "); valueString.append("ON"); }
667         else { if (!valueString.empty()) valueString.append(", "); valueString.append("OFF"); }
668     }
669     if ((value&osg::StateAttribute::OVERRIDE)!=0) { if (!valueString.empty()) valueString.append(", "); valueString.append("OVERRIDE"); }
670     if ((value&osg::StateAttribute::PROTECTED)!=0) { if (!valueString.empty()) valueString.append(", "); valueString.append("PROTECTED"); }
671     if ((value&osg::StateAttribute::INHERIT)!=0) { if (!valueString.empty()) valueString.append(", "); valueString.append("INHERIT"); }
672     return valueString;
673 }
674 
callStateSetSet(lua_State * _lua)675 static int callStateSetSet(lua_State* _lua)
676 {
677     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
678     int n = lua_gettop(_lua);    /* number of arguments */
679     if (n<2 || lua_type(_lua, 1)!=LUA_TTABLE) return 0;
680 
681     osg::StateSet* stateset  = lse->getObjectFromTable<osg::StateSet>(1);
682     if (!stateset)
683     {
684         OSG_NOTICE<<"Warning: StateSet:add() can only be called on a StateSet"<<std::endl;
685         return 0;
686     }
687 
688     if (lua_type(_lua,2)==LUA_TTABLE)
689     {
690         osg::Object* po  = lse->getObjectFromTable<osg::Object>(2);
691         osg::StateAttribute* sa = dynamic_cast<osg::StateAttribute*>(po);
692         osg::Uniform* uniform = dynamic_cast<osg::Uniform*>(po);
693 
694         osg::StateAttribute::OverrideValue value=osg::StateAttribute::ON;
695         bool setOnOff = false;
696         if (n>=3 && lua_type(_lua,3)==LUA_TSTRING)
697         {
698             value = convertStringToStateAttributeValue(lua_tostring(_lua, 3), value, setOnOff);
699         }
700 
701         if (sa)
702         {
703             if (setOnOff)
704             {
705                 if (sa->isTextureAttribute()) stateset->setTextureAttributeAndModes(0, sa, value);
706                 else  stateset->setAttributeAndModes(sa, value);
707             }
708             else
709             {
710                 if (sa->isTextureAttribute()) stateset->setTextureAttribute(0, sa, value);
711                 else  stateset->setAttribute(sa, value);
712             }
713             return 0;
714         }
715         else if (uniform)
716         {
717             stateset->addUniform(uniform, value);
718             return 0;
719         }
720     }
721     else if (lua_type(_lua,2)==LUA_TNUMBER)
722     {
723         double index = lua_tonumber(_lua, 2);
724         if (n>=3)
725         {
726             if (lua_type(_lua,3)==LUA_TTABLE)
727             {
728                 osg::Object* po  = lse->getObjectFromTable<osg::Object>(3);
729                 osg::StateAttribute* sa = dynamic_cast<osg::StateAttribute*>(po);
730 
731                 osg::StateAttribute::OverrideValue value=osg::StateAttribute::ON;
732                 bool setOnOff = false;
733                 if (n>=4 && lua_type(_lua,4)==LUA_TSTRING)
734                 {
735                     value = convertStringToStateAttributeValue(lua_tostring(_lua, 4), value, setOnOff);
736                 }
737 
738                 if (sa)
739                 {
740                     if (setOnOff)
741                     {
742                         stateset->setTextureAttributeAndModes(static_cast<unsigned int>(index), sa, value);
743                     }
744                     else
745                     {
746                         stateset->setTextureAttribute(static_cast<unsigned int>(index), sa, value);
747                     }
748                     return 0;
749                 }
750             }
751             else if (lua_type(_lua,3)==LUA_TSTRING)
752             {
753                 std::string modeString = lua_tostring(_lua, 3);
754                 GLenum mode = lse->lookUpGLenumValue(modeString);
755 
756                 osg::StateAttribute::OverrideValue value=osg::StateAttribute::ON;
757                 bool setOnOff = false;
758                 if (n>=4 && lua_type(_lua,4)==LUA_TSTRING)
759                 {
760                     value = convertStringToStateAttributeValue(lua_tostring(_lua, 4), value, setOnOff);
761                 }
762                 stateset->setTextureMode(static_cast<unsigned int>(index), mode, value);
763                 return 0;
764             }
765         }
766     }
767     else if (lua_type(_lua,2)==LUA_TSTRING)
768     {
769         std::string key = lua_tostring(_lua, 2);
770         GLenum mode = lse->lookUpGLenumValue(key);
771         if (n>=3)
772         {
773             if (mode)
774             {
775                 osg::StateAttribute::OverrideValue value=osg::StateAttribute::ON;
776                 bool setOnOff = false;
777                 if (lua_type(_lua,3)==LUA_TSTRING)
778                 {
779                     value = convertStringToStateAttributeValue(lua_tostring(_lua, 3), value, setOnOff);
780                 }
781 
782                 stateset->setMode(mode, value);
783                 return 0;
784             }
785             else
786             {
787                 std::string value;
788                 if (lua_type(_lua,3)==LUA_TSTRING)
789                 {
790                     value = lua_tostring(_lua, 3);
791                 }
792                 stateset->setDefine(key, value);
793             }
794         }
795         else
796         {
797             if (mode)
798             {
799                 osg::StateAttribute::OverrideValue value=osg::StateAttribute::ON;
800                 stateset->setMode(mode, value);
801                 return 0;
802             }
803             else
804             {
805                 stateset->setDefine(key);
806             }
807         }
808     }
809 
810     OSG_NOTICE<<"Warning: StateSet:set() inappropriate parameters, use form:"<<std::endl;
811     OSG_NOTICE<<"   StateSet:set(modestring [,value=\"ON,OFF,OVERRIDE,PROTECTED\"]); "<<std::endl;
812     OSG_NOTICE<<"   StateSet:set(uniform [,value=\"ON,OFF,OVERRIDE,PROTECTED\"]); "<<std::endl;
813     OSG_NOTICE<<"   StateSet:set(attribute [,value=\"ON,OFF,OVERRIDE,PROTECTED\"]); "<<std::endl;
814     OSG_NOTICE<<"   StateSet:set(textureUnit, textureAttribute [,value=\"ON,OFF,OVERRIDE,PROTECTED\"]); "<<std::endl;
815     return 0;
816 }
817 
callStateSetGet(lua_State * _lua)818 static int callStateSetGet(lua_State* _lua)
819 {
820     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
821     int n = lua_gettop(_lua);    /* number of arguments */
822     if (n<2 || lua_type(_lua, 1)!=LUA_TTABLE) return 0;
823 
824     osg::StateSet* stateset  = lse->getObjectFromTable<osg::StateSet>(1);
825     if (!stateset)
826     {
827         OSG_NOTICE<<"Warning: StateSet:get() can only be called on a StateSet"<<std::endl;
828         return 0;
829     }
830 
831     if (lua_type(_lua,2)==LUA_TNUMBER)
832     {
833         if (n<3)
834         {
835             OSG_NOTICE<<"Warning: StateSet:get() must be in form get(textureUnit, ClassName|ModeName|ObjectName)"<<std::endl;
836             return 0;
837         }
838 
839         unsigned int index = static_cast<unsigned int>(lua_tonumber(_lua, 2));
840         if (lua_type(_lua,3)==LUA_TTABLE)
841         {
842             osg::Object* po  = lse->getObjectFromTable<osg::Object>(3);
843             osg::StateAttribute* sa = dynamic_cast<osg::StateAttribute*>(po);
844             if (sa && sa->isTextureAttribute())
845             {
846                 if (stateset->getTextureAttributeList().size()>index)
847                 {
848                     const osg::StateSet::AttributeList& al = stateset->getTextureAttributeList()[index];
849                     for(osg::StateSet::AttributeList::const_iterator itr = al.begin();
850                         itr != al.end();
851                         ++itr)
852                     {
853                         if (itr->second.first==sa)
854                         {
855                             lua_newtable(_lua);
856                             lua_pushstring(_lua, "attribute"); lse->pushObject(itr->second.first.get()); lua_settable(_lua, -3);
857                             lua_pushstring(_lua, "value"); lua_pushstring(_lua, convertStateAttributeValueToString(itr->second.second, false).c_str()); lua_settable(_lua, -3);
858                             return 1;
859                         }
860                     }
861                 }
862                 OSG_NOTICE<<"Warning: StateSet:get() Could not find attribute : "<<sa->className()<<std::endl;
863                 lua_pushnil(_lua);
864                 return 1;
865             }
866             lua_pushnil(_lua);
867             return 1;
868         }
869         else if (lua_type(_lua,3)==LUA_TSTRING)
870         {
871             std::string value = lua_tostring(_lua, 3);
872             // need to look for attribute of mode with specified value
873             if (stateset->getTextureAttributeList().size()>index)
874             {
875                 const osg::StateSet::AttributeList& al = stateset->getTextureAttributeList()[index];
876                 for(osg::StateSet::AttributeList::const_iterator itr = al.begin();
877                     itr != al.end();
878                     ++itr)
879                 {
880                     if (value == itr->second.first->className() ||
881                         value == itr->second.first->getName())
882                     {
883                         lua_newtable(_lua);
884                         lua_pushstring(_lua, "attribute"); lse->pushObject(itr->second.first.get()); lua_settable(_lua, -3);
885                         lua_pushstring(_lua, "value"); lua_pushstring(_lua, convertStateAttributeValueToString(itr->second.second, false).c_str()); lua_settable(_lua, -3);
886                         return 1;
887                     }
888                 }
889             }
890             if (stateset->getTextureModeList().size()>index)
891             {
892                 osg::StateAttribute::GLMode mode = lse->lookUpGLenumValue(value);
893                 const osg::StateSet::ModeList& ml = stateset->getTextureModeList()[index];
894                 for(osg::StateSet::ModeList::const_iterator itr = ml.begin();
895                     itr != ml.end();
896                     ++itr)
897                 {
898                     if (mode == itr->first)
899                     {
900                         lua_pushstring(_lua, convertStateAttributeValueToString(itr->second, true).c_str());
901                         return 1;
902                     }
903                 }
904             }
905 
906             OSG_NOTICE<<"Warning: StateSet:get() Could not find attribute : "<<value<<std::endl;
907             lua_pushnil(_lua);
908             return 1;
909         }
910     }
911     else if (lua_type(_lua,2)==LUA_TTABLE)
912     {
913         osg::Object* po  = lse->getObjectFromTable<osg::Object>(2);
914         osg::StateAttribute* sa = dynamic_cast<osg::StateAttribute*>(po);
915         osg::Uniform* uniform = dynamic_cast<osg::Uniform*>(po);
916 
917         if (sa && sa->isTextureAttribute() && stateset->getTextureAttributeList().size()>0)
918         {
919             const osg::StateSet::AttributeList& al = stateset->getTextureAttributeList()[0];
920             for(osg::StateSet::AttributeList::const_iterator itr = al.begin();
921                 itr != al.end();
922                 ++itr)
923             {
924                 if (itr->second.first==sa)
925                 {
926                     lua_newtable(_lua);
927                     lua_pushstring(_lua, "attribute"); lse->pushObject(itr->second.first.get()); lua_settable(_lua, -3);
928                     lua_pushstring(_lua, "value"); lua_pushstring(_lua, convertStateAttributeValueToString(itr->second.second, false).c_str()); lua_settable(_lua, -3);
929                     return 1;
930                 }
931             }
932             OSG_NOTICE<<"Warning: StateSet:get("<<sa->className()<<") Could not find attribute"<<std::endl;
933             lua_pushnil(_lua);
934             return 1;
935         }
936         else if (sa)
937         {
938             const osg::StateSet::AttributeList& al = stateset->getAttributeList();
939             for(osg::StateSet::AttributeList::const_iterator itr = al.begin();
940                 itr != al.end();
941                 ++itr)
942             {
943                 if (itr->second.first==sa)
944                 {
945                     lua_newtable(_lua);
946                     lua_pushstring(_lua, "attribute"); lse->pushObject(itr->second.first.get()); lua_settable(_lua, -3);
947                     lua_pushstring(_lua, "value"); lua_pushstring(_lua, convertStateAttributeValueToString(itr->second.second, false).c_str()); lua_settable(_lua, -3);
948                     return 1;
949                 }
950             }
951             OSG_NOTICE<<"Warning: StateSet:get("<<sa->className()<<") Could not find attribute"<<std::endl;
952             lua_pushnil(_lua);
953             return 1;
954         }
955         else if (uniform)
956         {
957             const osg::StateSet::UniformList& ul = stateset->getUniformList();
958             for(osg::StateSet::UniformList::const_iterator itr = ul.begin();
959                 itr != ul.end();
960                 ++itr)
961             {
962                 if (itr->second.first==uniform)
963                 {
964                     lua_newtable(_lua);
965                     lua_pushstring(_lua, "attribute"); lse->pushObject(itr->second.first.get()); lua_settable(_lua, -3);
966                     lua_pushstring(_lua, "value"); lua_pushstring(_lua, convertStateAttributeValueToString(itr->second.second, false).c_str()); lua_settable(_lua, -3);
967                     return 1;
968                 }
969             }
970             OSG_NOTICE<<"Warning: StateSet:get("<<sa->className()<<") Could not find uniform"<<std::endl;
971             lua_pushnil(_lua);
972             return 1;
973         }
974     }
975     else if (lua_type(_lua,2)==LUA_TSTRING)
976     {
977         std::string value = lua_tostring(_lua, 2);
978         const osg::StateSet::AttributeList& al = stateset->getAttributeList();
979         for(osg::StateSet::AttributeList::const_iterator itr = al.begin();
980             itr != al.end();
981             ++itr)
982         {
983             if (value == itr->second.first->className() ||
984                 value == itr->second.first->getName())
985             {
986                 lua_newtable(_lua);
987                 lua_pushstring(_lua, "attribute"); lse->pushObject(itr->second.first.get()); lua_settable(_lua, -3);
988                 lua_pushstring(_lua, "value"); lua_pushstring(_lua, convertStateAttributeValueToString(itr->second.second, false).c_str()); lua_settable(_lua, -3);
989                 return 1;
990             }
991         }
992 
993         const osg::StateSet::UniformList& ul = stateset->getUniformList();
994         for(osg::StateSet::UniformList::const_iterator itr = ul.begin();
995             itr != ul.end();
996             ++itr)
997         {
998             if (value == itr->second.first->className() ||
999                 value == itr->second.first->getName())
1000             {
1001                 lua_newtable(_lua);
1002                 lua_pushstring(_lua, "attribute"); lse->pushObject(itr->second.first.get()); lua_settable(_lua, -3);
1003                 lua_pushstring(_lua, "value"); lua_pushstring(_lua, convertStateAttributeValueToString(itr->second.second, false).c_str()); lua_settable(_lua, -3);
1004                 return 1;
1005             }
1006         }
1007 
1008         osg::StateAttribute::GLMode mode = lse->lookUpGLenumValue(value);
1009         const osg::StateSet::ModeList& ml = stateset->getModeList();
1010         for(osg::StateSet::ModeList::const_iterator itr = ml.begin();
1011             itr != ml.end();
1012             ++itr)
1013         {
1014             if (mode == itr->first)
1015             {
1016                 lua_pushstring(_lua, convertStateAttributeValueToString(itr->second, true).c_str());
1017                 return 1;
1018             }
1019         }
1020 
1021 
1022         const osg::StateSet::DefineList& dl = stateset->getDefineList();
1023         for(osg::StateSet::DefineList::const_iterator itr = dl.begin();
1024             itr != dl.end();
1025             ++itr)
1026         {
1027             if (value == itr->first)
1028             {
1029                 lua_pushstring(_lua, itr->second.first.c_str());
1030                 return 1;
1031             }
1032         }
1033 
1034         OSG_NOTICE<<"Warning: StateSet:get("<<value<<") Could not find matching mode or attribute"<<std::endl;
1035         lua_pushnil(_lua);
1036         return 1;
1037     }
1038 
1039     OSG_NOTICE<<"Warning: StateSet:get() inappropriate parameters, use form:"<<std::endl;
1040     OSG_NOTICE<<"   StateSet:get(modestring); "<<std::endl;
1041     OSG_NOTICE<<"   StateSet:get(uniformName); "<<std::endl;
1042     OSG_NOTICE<<"   StateSet:get(attributeNameOrClassType); "<<std::endl;
1043     OSG_NOTICE<<"   StateSet:get(textureUnit, textureNameOrClassType); "<<std::endl;
1044 
1045     lua_pushnil(_lua);
1046     return 1;
1047 }
1048 
callStateSetRemove(lua_State * _lua)1049 static int callStateSetRemove(lua_State* _lua)
1050 {
1051     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
1052     int n = lua_gettop(_lua);    /* number of arguments */
1053     if (n<2 || lua_type(_lua, 1)!=LUA_TTABLE) return 0;
1054 
1055     osg::StateSet* stateset  = lse->getObjectFromTable<osg::StateSet>(1);
1056     if (!stateset)
1057     {
1058             OSG_NOTICE<<"Warning: StateSet:remove() can only be called on a StateSet"<<std::endl;
1059             return 0;
1060     }
1061 
1062     if (lua_type(_lua,2)==LUA_TNUMBER)
1063     {
1064         if (n<3)
1065         {
1066             OSG_NOTICE<<"Warning: StateSet:remove() must be in form remove(textureUnit, textureAttribute)"<<std::endl;
1067             return 0;
1068         }
1069 
1070         unsigned int index = static_cast<unsigned int>(lua_tonumber(_lua, 2));
1071         if (lua_type(_lua,3)==LUA_TTABLE)
1072         {
1073             osg::Object* po  = lse->getObjectFromTable<osg::Object>(3);
1074             osg::StateAttribute* sa = dynamic_cast<osg::StateAttribute*>(po);
1075             stateset->removeTextureAttribute(static_cast<unsigned int>(index), sa);
1076             return 0;
1077         }
1078         else if (lua_type(_lua,3)==LUA_TSTRING)
1079         {
1080             std::string value = lua_tostring(_lua, 3);
1081             if (stateset->getTextureAttributeList().size()>index)
1082             {
1083                 const osg::StateSet::AttributeList& al = stateset->getTextureAttributeList()[index];
1084                 for(osg::StateSet::AttributeList::const_iterator itr = al.begin();
1085                     itr != al.end();
1086                     ++itr)
1087                 {
1088                     if (value == itr->second.first->className() ||
1089                         value == itr->second.first->getName())
1090                     {
1091                         stateset->removeTextureAttribute(index, itr->second.first.get());
1092                         return 0;
1093                     }
1094                 }
1095             }
1096 
1097             if (stateset->getTextureModeList().size()>index)
1098             {
1099                 osg::StateAttribute::GLMode mode = lse->lookUpGLenumValue(value);
1100                 const osg::StateSet::ModeList& ml = stateset->getTextureModeList()[static_cast<unsigned int>(index)];
1101                 for(osg::StateSet::ModeList::const_iterator itr = ml.begin();
1102                     itr != ml.end();
1103                     ++itr)
1104                 {
1105                     if (mode == itr->first)
1106                     {
1107                         stateset->removeTextureMode(static_cast<unsigned int>(index), mode);
1108                         return 1;
1109                     }
1110                 }
1111             }
1112 
1113             OSG_NOTICE<<"Warning: StateSet:remove("<<index<<", "<<value<<") could not find entry to remove."<<std::endl;
1114             return 0;
1115         }
1116     }
1117     else if (lua_type(_lua,2)==LUA_TTABLE)
1118     {
1119         osg::Object* po  = lse->getObjectFromTable<osg::Object>(2);
1120         osg::StateAttribute* sa = dynamic_cast<osg::StateAttribute*>(po);
1121         osg::Uniform* uniform = dynamic_cast<osg::Uniform*>(po);
1122 
1123         if (sa && sa->isTextureAttribute())
1124         {
1125             stateset->removeTextureAttribute(0, sa);
1126             return 0;
1127         }
1128         else if (sa)
1129         {
1130             stateset->removeAttribute(sa);
1131             return 0;
1132         }
1133         else if (uniform)
1134         {
1135             stateset->removeUniform(uniform);
1136             return 0;
1137         }
1138     }
1139     else if (lua_type(_lua,2)==LUA_TSTRING)
1140     {
1141         std::string value = lua_tostring(_lua, 2);
1142         const osg::StateSet::AttributeList& al = stateset->getAttributeList();
1143         for(osg::StateSet::AttributeList::const_iterator itr = al.begin();
1144             itr != al.end();
1145             ++itr)
1146         {
1147             if (value == itr->second.first->className() ||
1148                 value == itr->second.first->getName())
1149             {
1150                 stateset->removeAttribute(itr->second.first.get());
1151                 return 0;
1152             }
1153         }
1154 
1155         const osg::StateSet::UniformList& ul = stateset->getUniformList();
1156         for(osg::StateSet::UniformList::const_iterator itr = ul.begin();
1157             itr != ul.end();
1158             ++itr)
1159         {
1160             if (value == itr->second.first->className() ||
1161                 value == itr->second.first->getName())
1162             {
1163                 stateset->removeUniform(itr->second.first.get());
1164                 return 0;
1165             }
1166         }
1167 
1168         const osg::StateSet::DefineList& dl = stateset->getDefineList();
1169         for(osg::StateSet::DefineList::const_iterator itr = dl.begin();
1170             itr != dl.end();
1171             ++itr)
1172         {
1173             if (value == itr->first)
1174             {
1175                 stateset->removeDefine(value);
1176                 return 0;
1177             }
1178         }
1179 
1180         osg::StateAttribute::GLMode mode = lse->lookUpGLenumValue(value);
1181         const osg::StateSet::ModeList& ml = stateset->getModeList();
1182         for(osg::StateSet::ModeList::const_iterator itr = ml.begin();
1183             itr != ml.end();
1184             ++itr)
1185         {
1186             if (mode == itr->first)
1187             {
1188                 stateset->removeMode(mode);
1189                 return 1;
1190             }
1191         }
1192 
1193 
1194         OSG_NOTICE<<"Warning: StateSet:remove("<<value<<") could not find entry to remove."<<std::endl;
1195         return 0;
1196     }
1197 
1198     OSG_NOTICE<<"Warning: StateSet:remove() inappropriate parameters, use form:"<<std::endl;
1199     OSG_NOTICE<<"   StateSet:remove(uniform); "<<std::endl;
1200     OSG_NOTICE<<"   StateSet:remove(attribute); "<<std::endl;
1201     OSG_NOTICE<<"   StateSet:remove(textureUnit, textureAttribute); "<<std::endl;
1202     return 0;
1203 }
1204 
1205 //////////////////////////////////////////////////////////////////////////////////////
1206 //
1207 //  Image calling support
1208 //
callImageAllocate(lua_State * _lua)1209 static int callImageAllocate(lua_State* _lua)
1210 {
1211     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
1212     int n = lua_gettop(_lua);    /* number of arguments */
1213     if (n<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0;
1214 
1215     osg::Image* image  = lse->getObjectFromTable<osg::Image>(1);
1216     if (!image)
1217     {
1218         OSG_NOTICE<<"Warning: Image:allocate() can only be called on a Image"<<std::endl;
1219         return 0;
1220     }
1221 
1222     int s=0, t=0, r=0;
1223     GLenum pixelFormat=0;
1224     GLenum dataType = 0;
1225     int packing = 1;
1226 
1227     if (n>=2 && lua_isnumber(_lua, 2)) s = static_cast<int>(lua_tonumber(_lua, 2));
1228     if (n>=3 && lua_isnumber(_lua, 3)) t = static_cast<int>(lua_tonumber(_lua, 3));
1229     if (n>=4 && lua_isnumber(_lua, 4)) r = static_cast<int>(lua_tonumber(_lua, 4));
1230 
1231     if (n>=5)
1232     {
1233         if (lua_isnumber(_lua, 5)) pixelFormat = static_cast<int>(lua_tonumber(_lua, 5));
1234         else if (lua_isstring(_lua, 5))
1235         {
1236             pixelFormat = lse->lookUpGLenumValue(lua_tostring(_lua,5));
1237         }
1238     }
1239 
1240     if (n>=6)
1241     {
1242         if (lua_isnumber(_lua, 6)) dataType = static_cast<int>(lua_tonumber(_lua, 6));
1243         else if (lua_isstring(_lua, 6))
1244         {
1245             dataType = lse->lookUpGLenumValue(lua_tostring(_lua,6));
1246         }
1247     }
1248 
1249     if (n>=7)
1250     {
1251         if (lua_isnumber(_lua, 7)) packing = static_cast<int>(lua_tonumber(_lua, 7));
1252     }
1253 
1254 
1255     if (s<=0 || t<=0 || r<=0 || pixelFormat==0 || dataType==0)
1256     {
1257         OSG_NOTICE<<"Warning: Cannot not image:allocator("<<s<<", "<<t<<", "<<r<<", "<<pixelFormat<<", "<<dataType<<") a zero sized image, use non zero, positive values for s,t,r, pixelFormat and dataType."<<std::endl;
1258         return 0;
1259     }
1260 
1261     image->allocateImage(s,t,r,pixelFormat,dataType,packing);
1262 
1263     return 0;
1264 }
1265 
callImageS(lua_State * _lua)1266 static int callImageS(lua_State* _lua)
1267 {
1268     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
1269     int n = lua_gettop(_lua);    /* number of arguments */
1270     if (n<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0;
1271 
1272     osg::Image* image  = lse->getObjectFromTable<osg::Image>(1);
1273     if (!image)
1274     {
1275         OSG_NOTICE<<"Warning: Image:s() can only be called on a Image"<<std::endl;
1276         return 0;
1277     }
1278 
1279     lua_pushinteger(_lua, image->s());
1280 
1281     return 1;
1282 }
1283 
callImageT(lua_State * _lua)1284 static int callImageT(lua_State* _lua)
1285 {
1286     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
1287     int n = lua_gettop(_lua);    /* number of arguments */
1288     if (n<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0;
1289 
1290     osg::Image* image  = lse->getObjectFromTable<osg::Image>(1);
1291     if (!image)
1292     {
1293         OSG_NOTICE<<"Warning: Image:t() can only be called on a Image"<<std::endl;
1294         return 0;
1295     }
1296 
1297     lua_pushinteger(_lua, image->t());
1298 
1299     return 1;
1300 }
1301 
callImageR(lua_State * _lua)1302 static int callImageR(lua_State* _lua)
1303 {
1304     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
1305     int n = lua_gettop(_lua);    /* number of arguments */
1306     if (n<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0;
1307 
1308     osg::Image* image  = lse->getObjectFromTable<osg::Image>(1);
1309     if (!image)
1310     {
1311         OSG_NOTICE<<"Warning: Image:r() can only be called on a Image"<<std::endl;
1312         return 0;
1313     }
1314 
1315     lua_pushinteger(_lua, image->r());
1316 
1317     return 1;
1318 }
1319 
1320 // conversion of a lua value/table to a std::string, supports recursion when tables contain tables
cpp_tostring(lua_State * _lua,int index)1321 static std::string cpp_tostring(lua_State* _lua, int index)
1322 {
1323     if (!lua_istable(_lua, index))
1324     {
1325         const char* str = lua_tostring(_lua, index);
1326         if (str)
1327         {
1328             return str;
1329         }
1330         else
1331         {
1332             return "value-cannot-be-converted-to-string";
1333         }
1334     }
1335 
1336     // Push another reference to the table on top of the stack (so we know
1337     // where it is, and this function can work for negative, positive and
1338     // pseudo indices
1339     lua_pushvalue(_lua, index);
1340     // stack now contains: -1 => table
1341     lua_pushnil(_lua);
1342     // stack now contains: -1 => nil; -2 => table
1343     bool first = true;
1344     std::string str("{");
1345     while (lua_next(_lua, -2))
1346     {
1347         if (!first) str.append(", ");
1348         else first = false;
1349 
1350         // stack now contains: -1 => value; -2 => key; -3 => table
1351         // copy the key so that lua_tostring does not modify the original
1352         lua_pushvalue(_lua, -2);
1353         // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table
1354 
1355         // handle key
1356         if (lua_isstring(_lua, -1))
1357         {
1358             const char *key = lua_tostring(_lua, -1);
1359             if (key)
1360             {
1361                 str.append(key);
1362                 str.append("=");
1363             }
1364         }
1365 
1366         // handle value
1367         if (lua_istable(_lua, -2))
1368         {
1369             str.append(cpp_tostring(_lua,-2));
1370         }
1371         else if (lua_isfunction(_lua, -2))
1372         {
1373             str.append("function");
1374         }
1375         else if (lua_isnil(_lua, -2))
1376         {
1377             str.append("nil");
1378         }
1379         else if (lua_isstring(_lua,-2))
1380         {
1381             const char *value = lua_tostring(_lua, -2);
1382             str.append("\"");
1383             if (value)
1384             {
1385                 str.append(value);
1386             }
1387             str.append("\"");
1388         }
1389         else
1390         {
1391             const char *value = lua_tostring(_lua, -2);
1392             if (value)
1393             {
1394                 str.append(value);
1395             }
1396         }
1397 
1398         // pop value + copy of key, leaving original key
1399         lua_pop(_lua, 2);
1400         // stack now contains: -1 => key; -2 => table
1401     }
1402     str.append("}");
1403 
1404     // stack now contains: -1 => table (when lua_next returns 0 it pops the key
1405     // but does not push anything.)
1406     // Pop table
1407     lua_pop(_lua, 1);
1408     // Stack is now the same as it was on entry to this function
1409 
1410     return str;
1411 }
1412 
tostring(lua_State * _lua)1413 static int tostring(lua_State* _lua)
1414 {
1415     lua_pushstring(_lua, cpp_tostring(_lua,-1) .c_str());
1416     return 1;
1417 }
1418 
callImageGet(lua_State * _lua)1419 static int callImageGet(lua_State* _lua)
1420 {
1421     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
1422     int n = lua_gettop(_lua);    /* number of arguments */
1423     if (n<2 || lua_type(_lua, 1)!=LUA_TTABLE) return 0;
1424 
1425     osg::Image* image  = lse->getObjectFromTable<osg::Image>(1);
1426     if (!image)
1427     {
1428         OSG_NOTICE<<"Warning: Image:get() can only be called on a Image"<<std::endl;
1429         return 0;
1430     }
1431 
1432     int image_i = 0;
1433     int image_j = 0;
1434     int image_k = 0;
1435     if (n>=2 && lua_isnumber(_lua, 2)) image_i = static_cast<int>(lua_tonumber(_lua, 2));
1436     if (n>=3 && lua_isnumber(_lua, 3)) image_j = static_cast<int>(lua_tonumber(_lua, 3));
1437     if (n>=4 && lua_isnumber(_lua, 4)) image_k = static_cast<int>(lua_tonumber(_lua, 4));
1438 
1439     const unsigned char* ptr = image->data(image_i,image_j,image_k);
1440     unsigned int numComponents = osg::Image::computeNumComponents(image->getPixelFormat());
1441 
1442     // OSG_NOTICE<<"Need to implement Image::get("<<i<<", "<<j<<", "<<k<<") ptr="<<(void*)ptr<<", numComponents="<<numComponents<<std::endl;
1443 
1444     osg::Vec4d colour;
1445     switch(image->getDataType())
1446     {
1447         case(GL_BYTE): for(unsigned int i=0; i<numComponents; ++i) { colour[i] = static_cast<double>(*(reinterpret_cast<const char*>(ptr)+i)); } break;
1448         case(GL_UNSIGNED_BYTE): for(unsigned int i=0; i<numComponents; ++i) { colour[i] = static_cast<double>(*(ptr+i)); } break;
1449         case(GL_SHORT): for(unsigned int i=0; i<numComponents; ++i) { colour[i] = static_cast<double>(*(reinterpret_cast<const short*>(ptr)+i)); } break;
1450         case(GL_UNSIGNED_SHORT): for(unsigned int i=0; i<numComponents; ++i) { colour[i] = static_cast<double>(*(reinterpret_cast<const unsigned short*>(ptr)+i)); } break;
1451         case(GL_INT): for(unsigned int i=0; i<numComponents; ++i) { colour[i] = static_cast<double>(*(reinterpret_cast<const int*>(ptr)+i)); } break;
1452         case(GL_UNSIGNED_INT): for(unsigned int i=0; i<numComponents; ++i) { colour[i] = static_cast<double>(*(reinterpret_cast<const unsigned int*>(ptr)+i)); } break;
1453         case(GL_FLOAT): for(unsigned int i=0; i<numComponents; ++i) { colour[i] = static_cast<double>(*(reinterpret_cast<const float*>(ptr)+i)); } break;
1454         case(GL_DOUBLE): for(unsigned int i=0; i<numComponents; ++i) { colour[i] = static_cast<double>(*(reinterpret_cast<const double*>(ptr)+i)); } break;
1455         default:
1456             OSG_NOTICE<<"Warning: Unsupported DataType in Image::get()"<<std::endl;
1457             return 0;
1458     }
1459 
1460     switch(image->getPixelFormat())
1461     {
1462         case(GL_INTENSITY):     lua_pushnumber(_lua, colour[0]); return 1;
1463         case(GL_LUMINANCE):     lua_pushnumber(_lua, colour[0]); return 1;
1464         case(GL_ALPHA):         lua_pushnumber(_lua, colour[0]); return 1;
1465         case(GL_LUMINANCE_ALPHA):
1466         {
1467             lua_newtable(_lua); luaL_getmetatable(_lua, "LuaScriptEngine.Table"); lua_setmetatable(_lua, -2);
1468             lua_pushstring(_lua, "luminance"); lua_pushnumber(_lua, colour[0]); lua_settable(_lua, -3);
1469             lua_pushstring(_lua, "alpha"); lua_pushnumber(_lua, colour[1]); lua_settable(_lua, -3);
1470             return 1;
1471         }
1472         case(GL_RGB):
1473         {
1474             lua_newtable(_lua); luaL_getmetatable(_lua, "LuaScriptEngine.Table"); lua_setmetatable(_lua, -2);
1475             lua_pushstring(_lua, "red"); lua_pushnumber(_lua, colour[0]); lua_settable(_lua, -3);
1476             lua_pushstring(_lua, "green"); lua_pushnumber(_lua, colour[1]); lua_settable(_lua, -3);
1477             lua_pushstring(_lua, "blue"); lua_pushnumber(_lua, colour[2]); lua_settable(_lua, -3);
1478             return 1;
1479         }
1480         case(GL_RGBA):
1481         {
1482             lua_newtable(_lua); luaL_getmetatable(_lua, "LuaScriptEngine.Table"); lua_setmetatable(_lua, -2);
1483             lua_pushstring(_lua, "red"); lua_pushnumber(_lua, colour[0]); lua_settable(_lua, -3);
1484             lua_pushstring(_lua, "green"); lua_pushnumber(_lua, colour[1]); lua_settable(_lua, -3);
1485             lua_pushstring(_lua, "blue"); lua_pushnumber(_lua, colour[2]); lua_settable(_lua, -3);
1486             lua_pushstring(_lua, "alpha"); lua_pushnumber(_lua, colour[3]); lua_settable(_lua, -3);
1487             return 1;
1488         }
1489         case(GL_BGR):
1490         {
1491             lua_newtable(_lua); luaL_getmetatable(_lua, "LuaScriptEngine.Table"); lua_setmetatable(_lua, -2);
1492             lua_pushstring(_lua, "red"); lua_pushnumber(_lua, colour[2]); lua_settable(_lua, -3);
1493             lua_pushstring(_lua, "green"); lua_pushnumber(_lua, colour[1]); lua_settable(_lua, -3);
1494             lua_pushstring(_lua, "blue"); lua_pushnumber(_lua, colour[0]); lua_settable(_lua, -3);
1495             return 1;
1496         }
1497         case(GL_BGRA):
1498         {
1499             lua_newtable(_lua); luaL_getmetatable(_lua, "LuaScriptEngine.Table"); lua_setmetatable(_lua, -2);
1500             lua_pushstring(_lua, "red"); lua_pushnumber(_lua, colour[2]); lua_settable(_lua, -3);
1501             lua_pushstring(_lua, "green"); lua_pushnumber(_lua, colour[1]); lua_settable(_lua, -3);
1502             lua_pushstring(_lua, "blue"); lua_pushnumber(_lua, colour[0]); lua_settable(_lua, -3);
1503             lua_pushstring(_lua, "alpha"); lua_pushnumber(_lua, colour[3]); lua_settable(_lua, -3);
1504             return 1;
1505         }
1506     }
1507 
1508     OSG_NOTICE<<"Warning: Image:get() unsupported PixelFormat"<<std::endl;
1509     return 0;
1510 }
1511 
setImageColour(osg::Image * image,int image_i,int image_j,int image_k,const osg::Vec4d & colourToWrite)1512 static void setImageColour(osg::Image* image, int image_i, int image_j, int image_k, const osg::Vec4d& colourToWrite)
1513 {
1514     if (image_i>=image->s() || image_j>=image->t() || image_k>=image->r())
1515     {
1516         OSG_NOTICE<<"Warning: Image::set("<<image_i<<", "<<image_j<<", "<<image_k<<") out of range"<<std::endl;
1517         return;
1518     }
1519 
1520     unsigned char* ptr = image->data(image_i,image_j,image_k);
1521     unsigned int numComponents = osg::Image::computeNumComponents(image->getPixelFormat());
1522 
1523     switch(image->getDataType())
1524     {
1525         case(GL_BYTE): for(unsigned int i=0; i<numComponents; ++i) { *(reinterpret_cast<char*>(ptr)+i) = static_cast<char>(colourToWrite[i]); } break;
1526         case(GL_UNSIGNED_BYTE): for(unsigned int i=0; i<numComponents; ++i) { *(reinterpret_cast<unsigned char*>(ptr)+i) = static_cast<unsigned char>(colourToWrite[i]); } break;
1527         case(GL_SHORT): for(unsigned int i=0; i<numComponents; ++i) { *(reinterpret_cast<short*>(ptr)+i) = static_cast<short>(colourToWrite[i]); } break;
1528         case(GL_UNSIGNED_SHORT): for(unsigned int i=0; i<numComponents; ++i) { *(reinterpret_cast<unsigned short*>(ptr)+i) = static_cast<unsigned short>(colourToWrite[i]); } break;
1529         case(GL_INT): for(unsigned int i=0; i<numComponents; ++i) {  *(reinterpret_cast<int*>(ptr)+i) = static_cast<int>(colourToWrite[i]); } break;
1530         case(GL_UNSIGNED_INT): for(unsigned int i=0; i<numComponents; ++i) { *(reinterpret_cast<unsigned int*>(ptr)+i) = static_cast<unsigned int>(colourToWrite[i]); } break;
1531         case(GL_FLOAT): for(unsigned int i=0; i<numComponents; ++i) { *(reinterpret_cast<float*>(ptr)+i) = static_cast<float>(colourToWrite[i]); } break;
1532         case(GL_DOUBLE): for(unsigned int i=0; i<numComponents; ++i) { *(reinterpret_cast<double*>(ptr)+i) = static_cast<double>(colourToWrite[i]); } break;
1533         default:
1534             OSG_NOTICE<<"Warning: Unsupported DataType in Image::set()"<<std::endl;
1535             return;
1536     }
1537 }
1538 
callImageSet(lua_State * _lua)1539 static int callImageSet(lua_State* _lua)
1540 {
1541     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
1542     int n = lua_gettop(_lua);    /* number of arguments */
1543     if (n<2 || lua_type(_lua, 1)!=LUA_TTABLE) return 0;
1544 
1545     osg::Image* image  = lse->getObjectFromTable<osg::Image>(1);
1546     if (!image)
1547     {
1548         OSG_NOTICE<<"Warning: Image:set() can only be called on a Image"<<std::endl;
1549         return 0;
1550     }
1551 
1552     bool positionSet = false;
1553     int image_i = 0;
1554     int image_j = 0;
1555     int image_k = 0;
1556     if (n>=3 && lua_isnumber(_lua, 2)) { image_i = static_cast<int>(lua_tonumber(_lua, 2)); positionSet = true; }
1557     if (n>=4 && lua_isnumber(_lua, 3)) { image_j = static_cast<int>(lua_tonumber(_lua, 3)); positionSet = true; }
1558     if (n>=5 && lua_isnumber(_lua, 4)) { image_k = static_cast<int>(lua_tonumber(_lua, 4)); positionSet = true; }
1559 
1560     osg::Vec4d colour(1.0,1.0,1.0,1.0);
1561     if (lua_isnumber(_lua, n))
1562     {
1563         colour[0] = colour[1] = colour[2] = colour[3] = lua_tonumber(_lua, n);
1564     }
1565     else if (lua_istable(_lua, n))
1566     {
1567         lua_getfield(_lua, n, "intensity");
1568         if (lua_isnumber(_lua, -1)) { double i = lua_tonumber(_lua, -1); colour[0] = i; colour[1] = i; colour[2] = i; colour[3] = i; }
1569         lua_pop(_lua, 1);
1570 
1571         lua_getfield(_lua, n, "i");
1572         if (lua_isnumber(_lua, -1)) { double i = lua_tonumber(_lua, -1); colour[0] = i; colour[1] = i; colour[2] = i; colour[3] = i; }
1573         lua_pop(_lua, 1);
1574 
1575 
1576         lua_getfield(_lua, n, "luminance");
1577         if (lua_isnumber(_lua, -1)) { double l = lua_tonumber(_lua, -1); colour[0] = l; colour[1] = l; colour[2] = l; }
1578         lua_pop(_lua, 1);
1579 
1580         lua_getfield(_lua, n, "l");
1581         if (lua_isnumber(_lua, -1)) { double l = lua_tonumber(_lua, -1); colour[0] = l; colour[1] = l; colour[2] = l; }
1582         lua_pop(_lua, 1);
1583 
1584 
1585         lua_getfield(_lua, n, "alpha");
1586         if (lua_isnumber(_lua, -1)) { double a = lua_tonumber(_lua, -1); colour[3] = a; }
1587         lua_pop(_lua, 1);
1588 
1589         lua_getfield(_lua, n, "a");
1590         if (lua_isnumber(_lua, -1)) { double a = lua_tonumber(_lua, -1); colour[3] = a; }
1591         lua_pop(_lua, 1);
1592 
1593 
1594         lua_getfield(_lua, n, "red");
1595         if (lua_isnumber(_lua, -1)) { double r = lua_tonumber(_lua, -1); colour[0] = r; }
1596         lua_pop(_lua, 1);
1597 
1598         lua_getfield(_lua, n, "r");
1599         if (lua_isnumber(_lua, -1)) { double r = lua_tonumber(_lua, -1); colour[0] = r; }
1600         lua_pop(_lua, 1);
1601 
1602 
1603         lua_getfield(_lua, n, "green");
1604         if (lua_isnumber(_lua, -1)) { double g = lua_tonumber(_lua, -1); colour[1] = g; }
1605         lua_pop(_lua, 1);
1606 
1607         lua_getfield(_lua, n, "g");
1608         if (lua_isnumber(_lua, -1)) { double g = lua_tonumber(_lua, -1); colour[1] = g; }
1609         lua_pop(_lua, 1);
1610 
1611 
1612         lua_getfield(_lua, n, "blue");
1613         if (lua_isnumber(_lua, -1)) { double b = lua_tonumber(_lua, -1); colour[2] = b; }
1614         lua_pop(_lua, 1);
1615 
1616         lua_getfield(_lua, n, "b");
1617         if (lua_isnumber(_lua, -1)) { double b = lua_tonumber(_lua, -1); colour[2] = b; }
1618         lua_pop(_lua, 1);
1619 
1620     }
1621 
1622     // repack the colour data to the final destination form
1623     osg::Vec4d colourToWrite = colour;
1624     switch(image->getPixelFormat())
1625     {
1626         case(GL_INTENSITY):     colourToWrite[0] = colour[0]; break;
1627         case(GL_LUMINANCE):     colourToWrite[0] = colour[0]; break;
1628         case(GL_ALPHA):         colourToWrite[0] = colour[3]; break;
1629         case(GL_LUMINANCE_ALPHA):
1630         {
1631             colourToWrite[0] = colour[0];
1632             colourToWrite[1] = colour[3];
1633             break;
1634         }
1635         case(GL_RGB):
1636         case(GL_RGBA):
1637         {
1638             // nothing to do as data is already in the correct form
1639             break;
1640         }
1641         case(GL_BGR):
1642         case(GL_BGRA):
1643         {
1644             colourToWrite[0] = colour[2];
1645             colourToWrite[1] = colour[1];
1646             colourToWrite[2] = colour[0];
1647             colourToWrite[3] = colour[3];
1648             return 1;
1649         }
1650     }
1651 
1652     if (positionSet)
1653     {
1654         setImageColour(image, image_i,image_j,image_k, colourToWrite);
1655     }
1656     else
1657     {
1658         for(int k=0; k<image->r(); ++k)
1659         {
1660             for(int j=0; j<image->t(); ++j)
1661             {
1662                 for(int i=0; i<image->s(); ++i)
1663                 {
1664                     setImageColour(image, i,j,k, colourToWrite);
1665                 }
1666             }
1667         }
1668     }
1669 
1670     return 0;
1671 }
1672 
1673 //////////////////////////////////////////////////////////////////////////////////////
1674 //
1675 //  Node Parent
1676 //
callGetParent(lua_State * _lua)1677 static int callGetParent(lua_State* _lua)
1678 {
1679     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
1680     int n = lua_gettop(_lua);    /* number of arguments */
1681     if (n<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0;
1682 
1683     osg::Node* node  = lse->getObjectFromTable<osg::Node>(1);
1684     if (!node)
1685     {
1686         OSG_NOTICE<<"Warning: Node::getParent() can only be called on a Node"<<std::endl;
1687         return 0;
1688     }
1689 
1690     int index = 0;
1691     if (n>=2 && lua_isnumber(_lua, 2))
1692     {
1693         index = static_cast<int>(lua_tonumber(_lua, 2));
1694         if (index>=0 && index<static_cast<int>(node->getNumParents()))
1695         {
1696             lse->pushObject(node->getParent(0));
1697             return 1;
1698         }
1699         else
1700         {
1701             OSG_NOTICE<<"Warning: Call to node:getParent(index) has an out of range index."<<std::endl;
1702             return 0;
1703         }
1704     }
1705     else
1706     {
1707         OSG_NOTICE<<"Warning: node:getParent() requires a integer parameter."<<std::endl;
1708         return 0;
1709     }
1710 }
1711 
callGetNumParents(lua_State * _lua)1712 static int callGetNumParents(lua_State* _lua)
1713 {
1714     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
1715     int n = lua_gettop(_lua);    /* number of arguments */
1716     if (n<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0;
1717 
1718     osg::Node* node  = lse->getObjectFromTable<osg::Node>(1);
1719     if (!node)
1720     {
1721         OSG_NOTICE<<"Warning: Node::getNumParents() can only be called on a Node"<<std::endl;
1722         return 0;
1723     }
1724 
1725     lua_pushnumber(_lua, node->getNumParents());
1726     return 1;
1727 }
1728 
1729 //////////////////////////////////////////////////////////////////////////////////////
1730 //
1731 //  Method calling support
1732 //
callClassMethod(lua_State * _lua)1733 static int callClassMethod(lua_State* _lua)
1734 {
1735     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
1736     std::string methodName = lua_tostring(_lua, lua_upvalueindex(2));
1737     int n = lua_gettop(_lua);    /* number of arguments */
1738 
1739     if (n>=1 && lua_type(_lua, 1)==LUA_TTABLE)
1740     {
1741         osg::Object* object  = lse->getObjectFromTable<osg::Object>(1);
1742         const std::string compoundClassName = lse->getObjectCompoundClassName(1); // object->getCompoundClassName();
1743         // OSG_NOTICE<<"callClassMethod() on "<<object->className()<<" method name "<<methodName<<", stored compoundClassName "<<compoundClassName<<std::endl;
1744 
1745         // need to put within a c function
1746         osg::Parameters inputParameters, outputParameters;
1747         for(int i=2; i<=n; ++i)
1748         {
1749             // OSG_NOTICE<<" need to push parameter "<<lua_typename(_lua, lua_type(_lua, n))<<std::endl;
1750             inputParameters.insert(inputParameters.begin(), lse->popParameterObject());
1751         }
1752 
1753         if (lse->getClassInterface().run(object, compoundClassName, methodName, inputParameters, outputParameters))
1754         {
1755             for(osg::Parameters::iterator itr = outputParameters.begin();
1756                 itr != outputParameters.end();
1757                 ++itr)
1758             {
1759                 // OSG_NOTICE<<" pushing return "<<(*itr)->className()<<std::endl;
1760                 lse->pushParameter(itr->get());
1761             }
1762             return outputParameters.size();
1763         }
1764     }
1765     else
1766     {
1767         OSG_NOTICE<<"Warning: lua method called without passing object, use object::method() convention."<<std::endl;
1768     }
1769 
1770     return 0;
1771 }
1772 
garabageCollectObject(lua_State * _lua)1773 static int garabageCollectObject(lua_State* _lua)
1774 {
1775     int n = lua_gettop(_lua);    /* number of arguments */
1776     if (n==1)
1777     {
1778         if (lua_type(_lua, 1)==LUA_TUSERDATA)
1779         {
1780             osg::Object* object = *const_cast<osg::Object**>(reinterpret_cast<const osg::Object**>(lua_touserdata(_lua, 1)));
1781             object->unref();
1782         }
1783     }
1784 
1785     return 0;
1786 }
1787 
newObject(lua_State * _lua)1788 static int newObject(lua_State * _lua)
1789 {
1790     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
1791 
1792     int n = lua_gettop(_lua);    /* number of arguments */
1793     if (n==1)
1794     {
1795         if (lua_type(_lua, 1)==LUA_TSTRING)
1796         {
1797             std::string compoundName = lua_tostring(_lua, 1);
1798 
1799             lse->createAndPushObject(compoundName);
1800             return 1;
1801         }
1802     }
1803     return 0;
1804 }
1805 
castObject(lua_State * _lua)1806 static int castObject(lua_State * _lua)
1807 {
1808     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
1809 
1810     int n = lua_gettop(_lua);    /* number of arguments */
1811     if (n==2)
1812     {
1813         if (lua_type(_lua, 1)==LUA_TSTRING && lua_type(_lua, 2)==LUA_TTABLE)
1814         {
1815             std::string new_compoundClassName = lua_tostring(_lua, 1);
1816             osg::Object* object  = lse->getObjectFromTable<osg::Object>(2);
1817 
1818             lse->pushAndCastObject(new_compoundClassName, object);
1819 
1820             return 1;
1821         }
1822     }
1823     return 0;
1824 }
1825 
readObjectFile(lua_State * _lua)1826 static int readObjectFile(lua_State * _lua)
1827 {
1828     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
1829 
1830     int n = lua_gettop(_lua);    /* number of arguments */
1831     if (n==1 && lua_type(_lua, 1)==LUA_TSTRING)
1832     {
1833         std::string filename = lua_tostring(_lua, 1);
1834         osg::ref_ptr<osg::Object> object = osgDB::readRefObjectFile(filename);
1835         if (object.valid())
1836         {
1837             lse->pushObject(object.get());
1838             return 1;
1839         }
1840     }
1841     return 0;
1842 }
1843 
readImageFile(lua_State * _lua)1844 static int readImageFile(lua_State * _lua)
1845 {
1846     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
1847 
1848     int n = lua_gettop(_lua);    /* number of arguments */
1849     if (n==1 && lua_type(_lua, 1)==LUA_TSTRING)
1850     {
1851         std::string filename = lua_tostring(_lua, 1);
1852         osg::ref_ptr<osg::Image> image = osgDB::readRefImageFile(filename);
1853         if (image.valid())
1854         {
1855             lse->pushObject(image.get());
1856             return 1;
1857         }
1858     }
1859     return 0;
1860 }
1861 
readShaderFile(lua_State * _lua)1862 static int readShaderFile(lua_State * _lua)
1863 {
1864     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
1865 
1866     int n = lua_gettop(_lua);    /* number of arguments */
1867     if (n==1 && lua_type(_lua, 1)==LUA_TSTRING)
1868     {
1869         std::string filename = lua_tostring(_lua, 1);
1870         osg::ref_ptr<osg::Shader> shader = osgDB::readRefShaderFile(filename);
1871         if (shader.valid())
1872         {
1873             lse->pushObject(shader.get());
1874             return 1;
1875         }
1876     }
1877     return 0;
1878 }
1879 
readNodeFile(lua_State * _lua)1880 static int readNodeFile(lua_State * _lua)
1881 {
1882     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
1883 
1884     int n = lua_gettop(_lua);    /* number of arguments */
1885     if (n==1 && lua_type(_lua, 1)==LUA_TSTRING)
1886     {
1887         std::string filename = lua_tostring(_lua, 1);
1888         osg::ref_ptr<osg::Node> node = osgDB::readRefNodeFile(filename);
1889         if (node.valid())
1890         {
1891             lse->pushObject(node.get());
1892             return 1;
1893         }
1894     }
1895     return 0;
1896 }
1897 
1898 
writeFile(lua_State * _lua)1899 static int writeFile(lua_State * _lua)
1900 {
1901     const LuaScriptEngine* lse = reinterpret_cast<const LuaScriptEngine*>(lua_topointer(_lua, lua_upvalueindex(1)));
1902 
1903     int n = lua_gettop(_lua);    /* number of arguments */
1904     if (n>=2 && lua_type(_lua, 1)==LUA_TTABLE && lua_type(_lua, 2)==LUA_TSTRING)
1905     {
1906         osg::Object* object  = lse->getObjectFromTable<osg::Object>(1);
1907         std::string filename = lua_tostring(_lua, 2);
1908         if (object)
1909         {
1910             osgDB::writeObjectFile(*object, filename);
1911             return 1;
1912         }
1913     }
1914     return 0;
1915 }
1916 
1917 
1918 
1919 
LuaScriptEngine()1920 LuaScriptEngine::LuaScriptEngine():
1921     osg::ScriptEngine("lua"),
1922     _lua(0),
1923     _scriptCount(0)
1924 {
1925     initialize();
1926 }
1927 
LuaScriptEngine(const LuaScriptEngine &,const osg::CopyOp &)1928 LuaScriptEngine::LuaScriptEngine(const LuaScriptEngine&, const osg::CopyOp&):
1929     osg::ScriptEngine("lua"),
1930     _lua(0),
1931     _scriptCount(0)
1932 {
1933     initialize();
1934 }
1935 
~LuaScriptEngine()1936 LuaScriptEngine::~LuaScriptEngine()
1937 {
1938     lua_close(_lua);
1939 }
1940 
createUniquieScriptName()1941 std::string LuaScriptEngine::createUniquieScriptName()
1942 {
1943     std::stringstream sstr;
1944     sstr<<"script_"<<_scriptCount;
1945     ++_scriptCount;
1946 
1947     return sstr.str();
1948 }
1949 
initialize()1950 void LuaScriptEngine::initialize()
1951 {
1952     _lua = luaL_newstate();
1953 
1954     luaL_openlibs(_lua);
1955 
1956     // provide global new method for creating osg::Object's.
1957     {
1958         lua_pushlightuserdata(_lua, this);
1959         lua_pushcclosure(_lua, newObject, 1);
1960         lua_setglobal(_lua, "new");
1961     }
1962 
1963     // provide global new method for casting osg::Object's.
1964     {
1965         lua_pushlightuserdata(_lua, this);
1966         lua_pushcclosure(_lua, castObject, 1);
1967         lua_setglobal(_lua, "cast");
1968     }
1969 
1970     // provide global new method for reading Objects
1971     {
1972         lua_pushlightuserdata(_lua, this);
1973         lua_pushcclosure(_lua, readObjectFile, 1);
1974         lua_setglobal(_lua, "readFile");
1975     }
1976 
1977     // provide global new method for reading Objects
1978     {
1979         lua_pushlightuserdata(_lua, this);
1980         lua_pushcclosure(_lua, readObjectFile, 1);
1981         lua_setglobal(_lua, "readObjectFile");
1982     }
1983 
1984     // provide global new method for reading Nodes
1985     {
1986         lua_pushlightuserdata(_lua, this);
1987         lua_pushcclosure(_lua, readNodeFile, 1);
1988         lua_setglobal(_lua, "readNodeFile");
1989     }
1990 
1991     // provide global new method for read Images
1992     {
1993         lua_pushlightuserdata(_lua, this);
1994         lua_pushcclosure(_lua, readImageFile, 1);
1995         lua_setglobal(_lua, "readImageFile");
1996     }
1997 
1998     // provide global new method for read Images
1999     {
2000         lua_pushlightuserdata(_lua, this);
2001         lua_pushcclosure(_lua, readShaderFile, 1);
2002         lua_setglobal(_lua, "readShaderFile");
2003     }
2004 
2005     // provide global new method for read Images
2006     {
2007         lua_pushlightuserdata(_lua, this);
2008         lua_pushcclosure(_lua, writeFile, 1);
2009         lua_setglobal(_lua, "writeFile");
2010     }
2011 
2012     // Set up the __newindex and __index methods for looking up implementations of Object properties
2013     {
2014         luaL_newmetatable(_lua, "LuaScriptEngine.Object");
2015 
2016         lua_pushstring(_lua, "__index");
2017         lua_pushlightuserdata(_lua, this);
2018         lua_pushcclosure(_lua, getProperty, 1);
2019         lua_settable(_lua, -3);
2020 
2021         lua_pushstring(_lua, "__newindex");
2022         lua_pushlightuserdata(_lua, this);
2023         lua_pushcclosure(_lua, setProperty, 1);
2024         lua_settable(_lua, -3);
2025 
2026         lua_pushstring(_lua, "__tostring");
2027         lua_pushlightuserdata(_lua, this);
2028         lua_pushcclosure(_lua, tostring, 1);
2029         lua_settable(_lua, -3);
2030 
2031         lua_pop(_lua,1);
2032     }
2033 
2034     // Set up the __tostring methods to be able to convert tables into strings so they can be output for debugging purposes.
2035     {
2036         luaL_newmetatable(_lua, "LuaScriptEngine.Table");
2037 
2038         lua_pushstring(_lua, "__tostring");
2039         lua_pushlightuserdata(_lua, this);
2040         lua_pushcclosure(_lua, tostring, 1);
2041         lua_settable(_lua, -3);
2042 
2043         lua_pop(_lua,1);
2044     }
2045 
2046     // Set up the __newindex and __index methods for looking up implementations of Object properties
2047     {
2048         luaL_newmetatable(_lua, "LuaScriptEngine.Container");
2049 
2050         lua_pushstring(_lua, "__index");
2051         lua_pushlightuserdata(_lua, this);
2052         lua_pushcclosure(_lua, getContainerProperty, 1);
2053         lua_settable(_lua, -3);
2054 
2055         lua_pushstring(_lua, "__newindex");
2056         lua_pushlightuserdata(_lua, this);
2057         lua_pushcclosure(_lua, setContainerProperty, 1);
2058         lua_settable(_lua, -3);
2059 
2060         lua_pop(_lua,1);
2061     }
2062 
2063     // Set up the __newindex and __index methods for looking up implementations of Object properties
2064     {
2065         luaL_newmetatable(_lua, "LuaScriptEngine.Map");
2066 
2067         lua_pushstring(_lua, "__index");
2068         lua_pushlightuserdata(_lua, this);
2069         lua_pushcclosure(_lua, getMapProperty, 1);
2070         lua_settable(_lua, -3);
2071 
2072         lua_pushstring(_lua, "__newindex");
2073         lua_pushlightuserdata(_lua, this);
2074         lua_pushcclosure(_lua, setMapProperty, 1);
2075         lua_settable(_lua, -3);
2076 
2077         lua_pop(_lua,1);
2078     }
2079 
2080     // Set up the __gc methods for looking up implementations of Object pointer to do the unref when the associated Lua object is destroyed.
2081     {
2082         luaL_newmetatable(_lua, "LuaScriptEngine.UnrefObject");
2083         lua_pushstring(_lua, "__gc");
2084         lua_pushlightuserdata(_lua, this);
2085         lua_pushcclosure(_lua, garabageCollectObject, 1);
2086         lua_settable(_lua, -3);
2087 
2088         lua_pop(_lua,1);
2089     }
2090 }
2091 
loadScript(osg::Script * script)2092 bool LuaScriptEngine::loadScript(osg::Script* script)
2093 {
2094     if (_loadedScripts.count(script)!=0) return true;
2095 
2096     int loadResult = luaL_loadstring(_lua, script->getScript().c_str());
2097     if (loadResult==0)
2098     {
2099         std::string scriptID = createUniquieScriptName();
2100 
2101         lua_pushvalue(_lua, -1);
2102         lua_setglobal(_lua, scriptID.c_str());
2103 
2104         _loadedScripts[script] = scriptID;
2105 
2106         return true;
2107     }
2108     else
2109     {
2110         OSG_NOTICE << "LuaScriptEngine::luaL_loadstring(Script*) error: " << lua_tostring(_lua, -1) << std::endl;
2111         return false;
2112     }
2113 }
2114 
2115 
run(osg::Script * script,const std::string & entryPoint,osg::Parameters & inputParameters,osg::Parameters & outputParameters)2116 bool LuaScriptEngine::run(osg::Script* script, const std::string& entryPoint, osg::Parameters& inputParameters, osg::Parameters& outputParameters)
2117 {
2118     if (!script || !_lua) return false;
2119 
2120 
2121     if (_loadedScripts.count(script)==0)
2122     {
2123         if (!loadScript(script)) return false;
2124 
2125         if (!entryPoint.empty())
2126         {
2127             if (lua_pcall(_lua, 0, 0, 0)!=0)
2128             {
2129                 OSG_NOTICE<< "error initialize script "<< lua_tostring(_lua, -1)<<std::endl;
2130                 return false;
2131             }
2132         }
2133     }
2134 
2135     int topBeforeCall = lua_gettop(_lua);
2136 
2137     if (entryPoint.empty())
2138     {
2139         ScriptMap::iterator itr = _loadedScripts.find(script);
2140         if (itr == _loadedScripts.end()) return false;
2141 
2142         std::string scriptID = itr->second;
2143 
2144         lua_getglobal(_lua, scriptID.c_str());
2145     }
2146     else
2147     {
2148         lua_getglobal(_lua, entryPoint.c_str()); /* function to be called */
2149     }
2150 
2151     for(osg::Parameters::const_iterator itr = inputParameters.begin();
2152         itr != inputParameters.end();
2153         ++itr)
2154     {
2155         pushParameter(itr->get());
2156     }
2157 
2158 
2159     if (lua_pcall(_lua, inputParameters.size(), LUA_MULTRET,0)!=0)
2160     {
2161         OSG_NOTICE<<"Lua error : "<<lua_tostring(_lua, -1)<<std::endl;
2162         return false;
2163     }
2164 
2165     int topAfterCall = lua_gettop(_lua);
2166     int numReturns = topAfterCall-topBeforeCall;
2167 
2168     outputParameters.clear();
2169 
2170     for(int i=0; i<numReturns; ++i)
2171     {
2172         osg::ref_ptr<osg::Object> obj = popParameterObject();
2173         if (obj.valid()) outputParameters.push_back(obj);
2174     }
2175 
2176     return true;
2177 }
2178 
2179 
2180 class PushStackValueVisitor : public osg::ValueObject::GetValueVisitor
2181 {
2182 public:
2183 
2184     const LuaScriptEngine* _lse;
2185     lua_State* _lua;
2186 
PushStackValueVisitor(const LuaScriptEngine * lse)2187     PushStackValueVisitor(const LuaScriptEngine* lse) : _lse(lse) { _lua = const_cast<LuaScriptEngine*>(lse)->getLuaState(); }
2188 
apply(bool value)2189     virtual void apply(bool value)                      { lua_pushboolean(_lua, value ? 1 : 0); }
apply(char value)2190     virtual void apply(char value)                      { lua_pushnumber(_lua, value); }
apply(unsigned char value)2191     virtual void apply(unsigned char value)             { lua_pushnumber(_lua, value); }
apply(short value)2192     virtual void apply(short value)                     { lua_pushnumber(_lua, value); }
apply(unsigned short value)2193     virtual void apply(unsigned short value)            { lua_pushnumber(_lua, value); }
apply(int value)2194     virtual void apply(int value)                       { lua_pushnumber(_lua, value); }
apply(unsigned int value)2195     virtual void apply(unsigned int value)              { lua_pushnumber(_lua, value); }
apply(float value)2196     virtual void apply(float value)                     { lua_pushnumber(_lua, value); }
apply(double value)2197     virtual void apply(double value)                    { lua_pushnumber(_lua, value); }
apply(const std::string & value)2198     virtual void apply(const std::string& value)        { lua_pushlstring(_lua, &value[0], value.size()); }
2199 
apply(const osg::Vec2b & value)2200     virtual void apply(const osg::Vec2b& value)         { _lse->pushValue(value); }
apply(const osg::Vec3b & value)2201     virtual void apply(const osg::Vec3b& value)         { _lse->pushValue(value); }
apply(const osg::Vec4b & value)2202     virtual void apply(const osg::Vec4b& value)         { _lse->pushValue(value); }
2203 
apply(const osg::Vec2ub & value)2204     virtual void apply(const osg::Vec2ub& value)         { _lse->pushValue(value); }
apply(const osg::Vec3ub & value)2205     virtual void apply(const osg::Vec3ub& value)         { _lse->pushValue(value); }
apply(const osg::Vec4ub & value)2206     virtual void apply(const osg::Vec4ub& value)         { _lse->pushValue(value); }
2207 
apply(const osg::Vec2s & value)2208     virtual void apply(const osg::Vec2s& value)         { _lse->pushValue(value); }
apply(const osg::Vec3s & value)2209     virtual void apply(const osg::Vec3s& value)         { _lse->pushValue(value); }
apply(const osg::Vec4s & value)2210     virtual void apply(const osg::Vec4s& value)         { _lse->pushValue(value); }
2211 
apply(const osg::Vec2us & value)2212     virtual void apply(const osg::Vec2us& value)         { _lse->pushValue(value); }
apply(const osg::Vec3us & value)2213     virtual void apply(const osg::Vec3us& value)         { _lse->pushValue(value); }
apply(const osg::Vec4us & value)2214     virtual void apply(const osg::Vec4us& value)         { _lse->pushValue(value); }
2215 
apply(const osg::Vec2i & value)2216     virtual void apply(const osg::Vec2i& value)         { _lse->pushValue(value); }
apply(const osg::Vec3i & value)2217     virtual void apply(const osg::Vec3i& value)         { _lse->pushValue(value); }
apply(const osg::Vec4i & value)2218     virtual void apply(const osg::Vec4i& value)         { _lse->pushValue(value); }
2219 
apply(const osg::Vec2ui & value)2220     virtual void apply(const osg::Vec2ui& value)         { _lse->pushValue(value); }
apply(const osg::Vec3ui & value)2221     virtual void apply(const osg::Vec3ui& value)         { _lse->pushValue(value); }
apply(const osg::Vec4ui & value)2222     virtual void apply(const osg::Vec4ui& value)         { _lse->pushValue(value); }
2223 
apply(const osg::Vec2f & value)2224     virtual void apply(const osg::Vec2f& value)         { _lse->pushValue(value); }
apply(const osg::Vec3f & value)2225     virtual void apply(const osg::Vec3f& value)         { _lse->pushValue(value); }
apply(const osg::Vec4f & value)2226     virtual void apply(const osg::Vec4f& value)         { _lse->pushValue(value); }
2227 
apply(const osg::Vec2d & value)2228     virtual void apply(const osg::Vec2d& value)         { _lse->pushValue(value); }
apply(const osg::Vec3d & value)2229     virtual void apply(const osg::Vec3d& value)         { _lse->pushValue(value); }
apply(const osg::Vec4d & value)2230     virtual void apply(const osg::Vec4d& value)         { _lse->pushValue(value); }
2231 
apply(const osg::Quat & value)2232     virtual void apply(const osg::Quat& value)          { _lse->pushValue(value); }
apply(const osg::Plane & value)2233     virtual void apply(const osg::Plane& value)         { _lse->pushValue(value); }
apply(const osg::Matrixf & value)2234     virtual void apply(const osg::Matrixf& value)       { _lse->pushValue(value); }
apply(const osg::Matrixd & value)2235     virtual void apply(const osg::Matrixd& value)       { _lse->pushValue(value); }
2236 };
2237 
2238 #if LUA_VERSION_NUM<=501
2239     #define lua_rawlen lua_strlen
2240 #endif
2241 
2242 class GetStackValueVisitor : public osg::ValueObject::SetValueVisitor
2243 {
2244 public:
2245 
2246     const LuaScriptEngine* _lse;
2247     lua_State* _lua;
2248     int _index;
2249     int _numberToPop;
2250     bool _success;
2251 
GetStackValueVisitor(const LuaScriptEngine * lse,int index)2252     GetStackValueVisitor(const LuaScriptEngine* lse, int index) : _lse(lse), _lua(0), _index(index), _numberToPop(0), _success(false) { _lua = const_cast<LuaScriptEngine*>(lse  )->getLuaState(); }
2253 
2254 
apply(bool & value)2255     virtual void apply(bool& value)             { if (lua_isboolean(_lua, _index)) { value = (lua_toboolean(_lua, _index)!=0); _success=true; _numberToPop = 1; } }
apply(char & value)2256     virtual void apply(char& value)             { if (lua_isnumber(_lua, _index)) { value = lua_tonumber(_lua, _index)!=0; _success=true; _numberToPop = 1; } }
apply(unsigned char & value)2257     virtual void apply(unsigned char& value)    { if (lua_isnumber(_lua, _index)) { value = lua_tonumber(_lua, _index)!=0; _success=true; _numberToPop = 1; } }
apply(short & value)2258     virtual void apply(short& value)            { if (lua_isnumber(_lua, _index)) { value = lua_tonumber(_lua, _index)!=0; _success=true; _numberToPop = 1; } }
apply(unsigned short & value)2259     virtual void apply(unsigned short& value)   { if (lua_isnumber(_lua, _index)) { value = lua_tonumber(_lua, _index)!=0; _success=true; _numberToPop = 1; } }
apply(int & value)2260     virtual void apply(int& value)              { if (lua_isnumber(_lua, _index)) { value = lua_tonumber(_lua, _index)!=0; _success=true; _numberToPop = 1; } }
apply(unsigned int & value)2261     virtual void apply(unsigned int& value)     { if (lua_isnumber(_lua, _index)) { value = lua_tonumber(_lua, _index)!=0; _success=true; _numberToPop = 1; } }
apply(float & value)2262     virtual void apply(float& value)            { if (lua_isnumber(_lua, _index)) { value = lua_tonumber(_lua, _index)!=0; _success=true; _numberToPop = 1; } }
apply(double & value)2263     virtual void apply(double& value)           { if (lua_isnumber(_lua, _index)) { value = lua_tonumber(_lua, _index)!=0; _success=true; _numberToPop = 1; } }
apply(std::string & value)2264     virtual void apply(std::string& value)      { if (lua_isstring(_lua, _index)) { value = std::string(lua_tostring(_lua, _index), lua_rawlen(_lua, _index)); _numberToPop = 1; } }
apply(osg::Vec2f & value)2265     virtual void apply(osg::Vec2f& value)       { if (_lse->getValue(_index, value)) { _success=true; _numberToPop = 2;} }
apply(osg::Vec3f & value)2266     virtual void apply(osg::Vec3f& value)       { if (_lse->getValue(_index, value)) { _success=true; _numberToPop = 2; } }
apply(osg::Vec4f & value)2267     virtual void apply(osg::Vec4f& value)       { if (_lse->getValue(_index, value)) { _success=true; _numberToPop = 4; } }
apply(osg::Vec2d & value)2268     virtual void apply(osg::Vec2d& value)       { if (_lse->getValue(_index, value)) { _success=true; _numberToPop = 2; } }
apply(osg::Vec3d & value)2269     virtual void apply(osg::Vec3d& value)       { if (_lse->getValue(_index, value)) { _success=true; _numberToPop = 3; } }
apply(osg::Vec4d & value)2270     virtual void apply(osg::Vec4d& value)       { if (_lse->getValue(_index, value)) { _success=true; _numberToPop = 4; } }
apply(osg::Quat & value)2271     virtual void apply(osg::Quat& value)        { if (_lse->getValue(_index, value)) { _success=true; _numberToPop = 4; } }
apply(osg::Plane & value)2272     virtual void apply(osg::Plane& value)       { if (_lse->getValue(_index, value)) { _success=true; _numberToPop = 4; } }
apply(osg::Matrixf & value)2273     virtual void apply(osg::Matrixf& value)     { if (_lse->getValue(_index, value)) { _success = true; _numberToPop = 16; } }
apply(osg::Matrixd & value)2274     virtual void apply(osg::Matrixd& value)     { if (_lse->getValue(_index, value)) { _success = true; _numberToPop = 16; } }
apply(osg::BoundingBoxf & value)2275     virtual void apply(osg::BoundingBoxf& value) { if (_lse->getValue(_index, value)) { _success=true; } }
apply(osg::BoundingBoxd & value)2276     virtual void apply(osg::BoundingBoxd& value) { if (_lse->getValue(_index, value)) { _success=true; } }
apply(osg::BoundingSpheref & value)2277     virtual void apply(osg::BoundingSpheref& value) { if (_lse->getValue(_index, value)) { _success=true; } }
apply(osg::BoundingSphered & value)2278     virtual void apply(osg::BoundingSphered& value) { if (_lse->getValue(_index, value)) { _success=true; } }
2279 };
2280 
pushPropertyToStack(osg::Object * object,const std::string & propertyName) const2281 int LuaScriptEngine::pushPropertyToStack(osg::Object* object, const std::string& propertyName) const
2282 {
2283     osgDB::BaseSerializer::Type type;
2284     if (!_ci.getPropertyType(object, propertyName, type))
2285     {
2286         if (_ci.hasMethod(object, propertyName))
2287         {
2288             lua_pushlightuserdata(_lua, const_cast<LuaScriptEngine*>(this));
2289             lua_pushstring(_lua, propertyName.c_str());
2290             lua_pushcclosure(_lua, callClassMethod, 2);
2291 
2292             return 1;
2293         }
2294 
2295         osg::Object* uo = osg::getUserObject(object, propertyName);
2296         LuaCallbackObject* lco = dynamic_cast<LuaCallbackObject*>(uo);
2297         if (lco)
2298         {
2299             lua_rawgeti(_lua, LUA_REGISTRYINDEX, lco->getRef());
2300             return 1;
2301         }
2302         else if (uo)
2303         {
2304             pushObject(uo);
2305             return 1;
2306         }
2307 
2308         OSG_INFO<<"LuaScriptEngine::pushPropertyToStack("<<object<<", "<<propertyName<<") no property found."<<std::endl;
2309         return 0;
2310     }
2311 
2312     switch(type)
2313     {
2314         case(osgDB::BaseSerializer::RW_BOOL):
2315         {
2316             bool value;
2317             if (_ci.getProperty(object, propertyName, value))
2318             {
2319                 lua_pushboolean(_lua, value ? 1 : 0);
2320                 return 1;
2321             }
2322             break;
2323         }
2324         case(osgDB::BaseSerializer::RW_STRING):
2325         {
2326             std::string value;
2327             if (_ci.getProperty(object, propertyName, value))
2328             {
2329                 lua_pushstring(_lua, value.c_str());
2330                 return 1;
2331             }
2332             break;
2333         }
2334         case(osgDB::BaseSerializer::RW_GLENUM):
2335         {
2336             GLenum value;
2337             if (_ci.getProperty(object, propertyName, value))
2338             {
2339                 std::string enumString = lookUpGLenumString(value);
2340                 lua_pushstring(_lua, enumString.c_str());
2341                 return 1;
2342             }
2343             break;
2344         }
2345         case(osgDB::BaseSerializer::RW_ENUM):
2346         {
2347             int value;
2348             if (_ci.getProperty(object, propertyName, value))
2349             {
2350                 osgDB::BaseSerializer* serializer = _ci.getSerializer(object, propertyName, type);
2351                 osgDB::IntLookup* lookup = serializer ? serializer->getIntLookup() : 0;
2352                 if (lookup)
2353                 {
2354                     std::string enumString = lookup->getString(value);
2355                     lua_pushstring(_lua, enumString.c_str());
2356                 }
2357                 else
2358                 {
2359                     lua_pushinteger(_lua, value);
2360                 }
2361                 return 1;
2362             }
2363             break;
2364         }
2365         case(osgDB::BaseSerializer::RW_SHORT):
2366         {
2367             short value;
2368             if (_ci.getProperty(object, propertyName, value))
2369             {
2370                 lua_pushinteger(_lua, value);
2371                 return 1;
2372             }
2373             break;
2374         }
2375         case(osgDB::BaseSerializer::RW_USHORT):
2376         {
2377             unsigned short value;
2378             if (_ci.getProperty(object, propertyName, value))
2379             {
2380                 lua_pushinteger(_lua, value);
2381                 return 1;
2382             }
2383             break;
2384         }
2385         case(osgDB::BaseSerializer::RW_INT):
2386         {
2387             int value;
2388             if (_ci.getProperty(object, propertyName, value))
2389             {
2390                 lua_pushinteger(_lua, value);
2391                 return 1;
2392             }
2393             break;
2394         }
2395         case(osgDB::BaseSerializer::RW_UINT):
2396         {
2397             unsigned int value;
2398             if (_ci.getProperty(object, propertyName, value))
2399             {
2400                 lua_pushinteger(_lua, value);
2401                 return 1;
2402             }
2403             break;
2404         }
2405         case(osgDB::BaseSerializer::RW_FLOAT):
2406         {
2407             float value;
2408             if (_ci.getProperty(object, propertyName, value))
2409             {
2410                 lua_pushnumber(_lua, value);
2411                 return 1;
2412             }
2413             break;
2414         }
2415         case(osgDB::BaseSerializer::RW_DOUBLE):
2416         {
2417             double value;
2418             if (_ci.getProperty(object, propertyName, value))
2419             {
2420                 lua_pushnumber(_lua, value);
2421                 return 1;
2422             }
2423             break;
2424         }
2425 
2426         case(osgDB::BaseSerializer::RW_VEC2B): if (getPropertyAndPushValue<osg::Vec2b>(object, propertyName)) return 1; break;
2427         case(osgDB::BaseSerializer::RW_VEC3B): if (getPropertyAndPushValue<osg::Vec3b>(object, propertyName)) return 1; break;
2428         case(osgDB::BaseSerializer::RW_VEC4B): if (getPropertyAndPushValue<osg::Vec4b>(object, propertyName)) return 1; break;
2429 
2430         case(osgDB::BaseSerializer::RW_VEC2UB): if (getPropertyAndPushValue<osg::Vec2ub>(object, propertyName)) return 1; break;
2431         case(osgDB::BaseSerializer::RW_VEC3UB): if (getPropertyAndPushValue<osg::Vec3ub>(object, propertyName)) return 1; break;
2432         case(osgDB::BaseSerializer::RW_VEC4UB): if (getPropertyAndPushValue<osg::Vec4ub>(object, propertyName)) return 1; break;
2433 
2434         case(osgDB::BaseSerializer::RW_VEC2S): if (getPropertyAndPushValue<osg::Vec2s>(object, propertyName)) return 1; break;
2435         case(osgDB::BaseSerializer::RW_VEC3S): if (getPropertyAndPushValue<osg::Vec3s>(object, propertyName)) return 1; break;
2436         case(osgDB::BaseSerializer::RW_VEC4S): if (getPropertyAndPushValue<osg::Vec4s>(object, propertyName)) return 1; break;
2437 
2438         case(osgDB::BaseSerializer::RW_VEC2US): if (getPropertyAndPushValue<osg::Vec2us>(object, propertyName)) return 1; break;
2439         case(osgDB::BaseSerializer::RW_VEC3US): if (getPropertyAndPushValue<osg::Vec3us>(object, propertyName)) return 1; break;
2440         case(osgDB::BaseSerializer::RW_VEC4US): if (getPropertyAndPushValue<osg::Vec4us>(object, propertyName)) return 1; break;
2441 
2442         case(osgDB::BaseSerializer::RW_VEC2I): if (getPropertyAndPushValue<osg::Vec2i>(object, propertyName)) return 1; break;
2443         case(osgDB::BaseSerializer::RW_VEC3I): if (getPropertyAndPushValue<osg::Vec3i>(object, propertyName)) return 1; break;
2444         case(osgDB::BaseSerializer::RW_VEC4I): if (getPropertyAndPushValue<osg::Vec4i>(object, propertyName)) return 1; break;
2445 
2446         case(osgDB::BaseSerializer::RW_VEC2UI): if (getPropertyAndPushValue<osg::Vec2ui>(object, propertyName)) return 1; break;
2447         case(osgDB::BaseSerializer::RW_VEC3UI): if (getPropertyAndPushValue<osg::Vec3ui>(object, propertyName)) return 1; break;
2448         case(osgDB::BaseSerializer::RW_VEC4UI): if (getPropertyAndPushValue<osg::Vec4ui>(object, propertyName)) return 1; break;
2449 
2450         case(osgDB::BaseSerializer::RW_VEC2F): if (getPropertyAndPushValue<osg::Vec2f>(object, propertyName)) return 1; break;
2451         case(osgDB::BaseSerializer::RW_VEC3F): if (getPropertyAndPushValue<osg::Vec3f>(object, propertyName)) return 1; break;
2452         case(osgDB::BaseSerializer::RW_VEC4F): if (getPropertyAndPushValue<osg::Vec4f>(object, propertyName)) return 1; break;
2453 
2454         case(osgDB::BaseSerializer::RW_VEC2D): if (getPropertyAndPushValue<osg::Vec2d>(object, propertyName)) return 1; break;
2455         case(osgDB::BaseSerializer::RW_VEC3D): if (getPropertyAndPushValue<osg::Vec3d>(object, propertyName)) return 1; break;
2456         case(osgDB::BaseSerializer::RW_VEC4D): if (getPropertyAndPushValue<osg::Vec4d>(object, propertyName)) return 1; break;
2457 
2458         case(osgDB::BaseSerializer::RW_QUAT): if (getPropertyAndPushValue<osg::Quat>(object, propertyName)) return 1; break;
2459         case(osgDB::BaseSerializer::RW_PLANE): if (getPropertyAndPushValue<osg::Plane>(object, propertyName)) return 1; break;
2460 
2461         #ifdef OSG_USE_FLOAT_MATRIX
2462         case(osgDB::BaseSerializer::RW_MATRIX):
2463 #endif
2464         case(osgDB::BaseSerializer::RW_MATRIXF):
2465         {
2466             osg::Matrixf value;
2467             if (_ci.getProperty(object, propertyName, value))
2468             {
2469                 pushValue(value);
2470                 return 1;
2471             }
2472             break;
2473         }
2474 #ifndef OSG_USE_FLOAT_MATRIX
2475         case(osgDB::BaseSerializer::RW_MATRIX):
2476 #endif
2477         case(osgDB::BaseSerializer::RW_MATRIXD):
2478         {
2479             osg::Matrixd value;
2480             if (_ci.getProperty(object, propertyName, value))
2481             {
2482                 pushValue(value);
2483                 return 1;
2484             }
2485             break;
2486         }
2487         case(osgDB::BaseSerializer::RW_BOUNDINGBOXF):
2488         {
2489             osg::BoundingBoxf value;
2490             if (_ci.getProperty(object, propertyName, value))
2491             {
2492                 pushValue(value);
2493                 return 1;
2494             }
2495             break;
2496         }
2497         case(osgDB::BaseSerializer::RW_BOUNDINGBOXD):
2498         {
2499             osg::BoundingBoxd value;
2500             if (_ci.getProperty(object, propertyName, value))
2501             {
2502                 pushValue(value);
2503                 return 1;
2504             }
2505             break;
2506         }
2507         case(osgDB::BaseSerializer::RW_BOUNDINGSPHEREF):
2508         {
2509             osg::BoundingSpheref value;
2510             if (_ci.getProperty(object, propertyName, value))
2511             {
2512                 pushValue(value);
2513                 return 1;
2514             }
2515             break;
2516         }
2517         case(osgDB::BaseSerializer::RW_BOUNDINGSPHERED):
2518         {
2519             osg::BoundingSphered value;
2520             if (_ci.getProperty(object, propertyName, value))
2521             {
2522                 pushValue(value);
2523                 return 1;
2524             }
2525             break;
2526         }
2527         case(osgDB::BaseSerializer::RW_LIST):
2528         {
2529             OSG_NOTICE<<"Need to implement RW_LIST support"<<std::endl;
2530             break;
2531         }
2532         case(osgDB::BaseSerializer::RW_IMAGE):
2533         case(osgDB::BaseSerializer::RW_OBJECT):
2534         {
2535             osg::Object* value = 0;
2536             if (_ci.getProperty(object, propertyName, value))
2537             {
2538                 pushObject(value);
2539                 return 1;
2540             }
2541             break;
2542         }
2543         case(osgDB::BaseSerializer::RW_VECTOR):
2544         case(osgDB::BaseSerializer::RW_MAP):
2545         {
2546             pushContainer(object, propertyName);
2547             return 1;
2548         }
2549         default:
2550             break;
2551     }
2552 
2553     OSG_NOTICE<<"LuaScriptEngine::pushPropertyToStack("<<object<<", "<<propertyName<<") property of type = "<<_ci.getTypeName(type)<<" error, not supported."<<std::endl;
2554     return 0;
2555 }
2556 
lookUpGLenumString(GLenum value) const2557 std::string LuaScriptEngine::lookUpGLenumString(GLenum value) const
2558 {
2559     osgDB::ObjectWrapperManager* ow = osgDB::Registry::instance()->getObjectWrapperManager();
2560 
2561     {
2562         const osgDB::IntLookup& lookup = ow->getLookupMap()["GL"];
2563         const osgDB::IntLookup::ValueToString& vts = lookup.getValueToString();
2564         osgDB::IntLookup::ValueToString::const_iterator itr = vts.find(value);
2565         if (itr!=vts.end()) return itr->second;
2566     }
2567 
2568     {
2569         const osgDB::IntLookup& lookup = ow->getLookupMap()["PrimitiveType"];
2570         const osgDB::IntLookup::ValueToString& vts = lookup.getValueToString();
2571         osgDB::IntLookup::ValueToString::const_iterator itr = vts.find(value);
2572         if (itr!=vts.end()) return itr->second;
2573     }
2574 
2575     OSG_NOTICE<<"Warning: LuaScriptEngine did not find valid GL enum value for GLenum value: "<<value<<std::endl;
2576 
2577     return std::string();
2578 }
2579 
lookUpGLenumValue(const std::string & str) const2580 GLenum LuaScriptEngine::lookUpGLenumValue(const std::string& str) const
2581 {
2582     osgDB::ObjectWrapperManager* ow = osgDB::Registry::instance()->getObjectWrapperManager();
2583 
2584     {
2585         const osgDB::IntLookup& lookup = ow->getLookupMap()["GL"];
2586         const osgDB::IntLookup::StringToValue& stv = lookup.getStringToValue();
2587         osgDB::IntLookup::StringToValue::const_iterator itr = stv.find(str);
2588         if (itr!=stv.end()) return itr->second;
2589     }
2590 
2591     {
2592         const osgDB::IntLookup& lookup = ow->getLookupMap()["PrimitiveType"];
2593         const osgDB::IntLookup::StringToValue& stv = lookup.getStringToValue();
2594         osgDB::IntLookup::StringToValue::const_iterator itr = stv.find(str);
2595         if (itr!=stv.end()) return itr->second;
2596     }
2597 
2598     OSG_NOTICE<<"Warning: LuaScriptEngine did not find valid GL enum value for string value: "<<str<<std::endl;
2599 
2600     return GL_NONE;
2601 }
2602 
2603 
pushDataToStack(SerializerScratchPad * ssp) const2604 int LuaScriptEngine::pushDataToStack(SerializerScratchPad* ssp) const
2605 {
2606     switch(ssp->dataType)
2607     {
2608         case(osgDB::BaseSerializer::RW_BOOL):
2609         {
2610             bool value;
2611             if (ssp->get(value))
2612             {
2613                 lua_pushboolean(_lua, value ? 1 : 0);
2614                 return 1;
2615             }
2616             break;
2617         }
2618         case(osgDB::BaseSerializer::RW_STRING):
2619         {
2620             std::string value;
2621             if (ssp->get(value))
2622             {
2623                 lua_pushstring(_lua, value.c_str());
2624                 return 1;
2625             }
2626             break;
2627         }
2628         case(osgDB::BaseSerializer::RW_GLENUM):
2629         {
2630             GLenum value;
2631             if (ssp->get(value))
2632             {
2633                 std::string enumString = lookUpGLenumString(value);
2634                 lua_pushstring(_lua, enumString.c_str());
2635                 return 1;
2636             }
2637             break;
2638         }
2639         case(osgDB::BaseSerializer::RW_ENUM):
2640         {
2641             int value;
2642             if (ssp->get(value))
2643             {
2644                 lua_pushinteger(_lua, value);
2645                 return 1;
2646             }
2647             break;
2648         }
2649         case(osgDB::BaseSerializer::RW_INT):
2650         {
2651             int value;
2652             if (ssp->get(value))
2653             {
2654                 lua_pushinteger(_lua, value);
2655                 return 1;
2656             }
2657             break;
2658         }
2659         case(osgDB::BaseSerializer::RW_UINT):
2660         {
2661             unsigned int value;
2662             if (ssp->get(value))
2663             {
2664                 lua_pushinteger(_lua, value);
2665                 return 1;
2666             }
2667             break;
2668         }
2669         case(osgDB::BaseSerializer::RW_SHORT):
2670         {
2671             short value;
2672             if (ssp->get(value))
2673             {
2674                 lua_pushinteger(_lua, value);
2675                 return 1;
2676             }
2677             break;
2678         }
2679         case(osgDB::BaseSerializer::RW_USHORT):
2680         {
2681             unsigned short value;
2682             if (ssp->get(value))
2683             {
2684                 lua_pushinteger(_lua, value);
2685                 return 1;
2686             }
2687             break;
2688         }
2689         case(osgDB::BaseSerializer::RW_FLOAT):
2690         {
2691             float value;
2692             if (ssp->get(value))
2693             {
2694                 lua_pushnumber(_lua, value);
2695                 return 1;
2696             }
2697             break;
2698         }
2699         case(osgDB::BaseSerializer::RW_DOUBLE):
2700         {
2701             double value;
2702             if (ssp->get(value))
2703             {
2704                 lua_pushnumber(_lua, value);
2705                 return 1;
2706             }
2707             break;
2708         }
2709 
2710         case(osgDB::BaseSerializer::RW_VEC2B): if (pushValueToStack<osg::Vec2b>(ssp)) return 1; break;
2711         case(osgDB::BaseSerializer::RW_VEC3B): if (pushValueToStack<osg::Vec3b>(ssp)) return 1; break;
2712         case(osgDB::BaseSerializer::RW_VEC4B): if (pushValueToStack<osg::Vec4b>(ssp)) return 1; break;
2713 
2714         case(osgDB::BaseSerializer::RW_VEC2UB): if (pushValueToStack<osg::Vec2ub>(ssp)) return 1; break;
2715         case(osgDB::BaseSerializer::RW_VEC3UB): if (pushValueToStack<osg::Vec3ub>(ssp)) return 1; break;
2716         case(osgDB::BaseSerializer::RW_VEC4UB): if (pushValueToStack<osg::Vec4ub>(ssp)) return 1; break;
2717 
2718         case(osgDB::BaseSerializer::RW_VEC2S): if (pushValueToStack<osg::Vec2s>(ssp)) return 1; break;
2719         case(osgDB::BaseSerializer::RW_VEC3S): if (pushValueToStack<osg::Vec3s>(ssp)) return 1; break;
2720         case(osgDB::BaseSerializer::RW_VEC4S): if (pushValueToStack<osg::Vec4s>(ssp)) return 1; break;
2721 
2722         case(osgDB::BaseSerializer::RW_VEC2US): if (pushValueToStack<osg::Vec2us>(ssp)) return 1; break;
2723         case(osgDB::BaseSerializer::RW_VEC3US): if (pushValueToStack<osg::Vec3us>(ssp)) return 1; break;
2724         case(osgDB::BaseSerializer::RW_VEC4US): if (pushValueToStack<osg::Vec4us>(ssp)) return 1; break;
2725 
2726         case(osgDB::BaseSerializer::RW_VEC2I): if (pushValueToStack<osg::Vec2i>(ssp)) return 1; break;
2727         case(osgDB::BaseSerializer::RW_VEC3I): if (pushValueToStack<osg::Vec3i>(ssp)) return 1; break;
2728         case(osgDB::BaseSerializer::RW_VEC4I): if (pushValueToStack<osg::Vec4i>(ssp)) return 1; break;
2729 
2730         case(osgDB::BaseSerializer::RW_VEC2UI): if (pushValueToStack<osg::Vec2ui>(ssp)) return 1; break;
2731         case(osgDB::BaseSerializer::RW_VEC3UI): if (pushValueToStack<osg::Vec3ui>(ssp)) return 1; break;
2732         case(osgDB::BaseSerializer::RW_VEC4UI): if (pushValueToStack<osg::Vec4ui>(ssp)) return 1; break;
2733 
2734         case(osgDB::BaseSerializer::RW_VEC2F): if (pushValueToStack<osg::Vec2f>(ssp)) return 1; break;
2735         case(osgDB::BaseSerializer::RW_VEC3F): if (pushValueToStack<osg::Vec3f>(ssp)) return 1; break;
2736         case(osgDB::BaseSerializer::RW_VEC4F): if (pushValueToStack<osg::Vec4f>(ssp)) return 1; break;
2737 
2738         case(osgDB::BaseSerializer::RW_VEC2D): if (pushValueToStack<osg::Vec2d>(ssp)) return 1; break;
2739         case(osgDB::BaseSerializer::RW_VEC3D): if (pushValueToStack<osg::Vec3d>(ssp)) return 1; break;
2740         case(osgDB::BaseSerializer::RW_VEC4D): if (pushValueToStack<osg::Vec4d>(ssp)) return 1; break;
2741 
2742         case(osgDB::BaseSerializer::RW_QUAT): if (pushValueToStack<osg::Quat>(ssp)) return 1; break;
2743         case(osgDB::BaseSerializer::RW_PLANE): if (pushValueToStack<osg::Plane>(ssp)) return 1; break;
2744 
2745 #ifdef OSG_USE_FLOAT_MATRIX
2746         case(osgDB::BaseSerializer::RW_MATRIX):
2747 #endif
2748         case(osgDB::BaseSerializer::RW_MATRIXF):
2749         {
2750             osg::Matrixf value;
2751             if (ssp->get(value))
2752             {
2753                 pushValue(value);
2754                 return 1;
2755             }
2756             break;
2757         }
2758 #ifndef OSG_USE_FLOAT_MATRIX
2759         case(osgDB::BaseSerializer::RW_MATRIX):
2760 #endif
2761         case(osgDB::BaseSerializer::RW_MATRIXD):
2762         {
2763             osg::Matrixd value;
2764             if (ssp->get(value))
2765             {
2766                 pushValue(value);
2767                 return 1;
2768             }
2769             break;
2770         }
2771         case(osgDB::BaseSerializer::RW_BOUNDINGBOXF):
2772         {
2773             osg::BoundingBoxf value;
2774             if (ssp->get(value))
2775             {
2776                 pushValue(value);
2777                 return 1;
2778             }
2779             break;
2780         }
2781         case(osgDB::BaseSerializer::RW_BOUNDINGBOXD):
2782         {
2783             osg::BoundingBoxd value;
2784             if (ssp->get(value))
2785             {
2786                 pushValue(value);
2787                 return 1;
2788             }
2789             break;
2790         }
2791         case(osgDB::BaseSerializer::RW_BOUNDINGSPHEREF):
2792         {
2793             osg::BoundingSpheref value;
2794             if (ssp->get(value))
2795             {
2796                 pushValue(value);
2797                 return 1;
2798             }
2799             break;
2800         }
2801         case(osgDB::BaseSerializer::RW_BOUNDINGSPHERED):
2802         {
2803             osg::BoundingSphered value;
2804             if (ssp->get(value))
2805             {
2806                 pushValue(value);
2807                 return 1;
2808             }
2809             break;
2810         }
2811         case(osgDB::BaseSerializer::RW_IMAGE):
2812         case(osgDB::BaseSerializer::RW_OBJECT):
2813         {
2814             osg::Object* value = 0;
2815             if (ssp->get(value))
2816             {
2817                 pushObject(value);
2818                 return 1;
2819             }
2820             break;
2821         }
2822         case(osgDB::BaseSerializer::RW_LIST):
2823         {
2824             break;
2825         }
2826         case(osgDB::BaseSerializer::RW_VECTOR):
2827         {
2828             break;
2829         }
2830         default:
2831             break;
2832     }
2833 
2834     OSG_NOTICE<<"LuaScriptEngine::pushDataToStack() property of type = "<<_ci.getTypeName(ssp->dataType)<<" error, not supported."<<std::endl;
2835     return 0;
2836 }
2837 
getDataFromStack(SerializerScratchPad * ssp,osgDB::BaseSerializer::Type type,int pos) const2838 int LuaScriptEngine::getDataFromStack(SerializerScratchPad* ssp, osgDB::BaseSerializer::Type type, int pos) const
2839 {
2840     pos = getAbsolutePos(pos);
2841 
2842     if (type==osgDB::BaseSerializer::RW_UNDEFINED) type = LuaScriptEngine::getType(pos);
2843 
2844     switch(type)
2845     {
2846         case(osgDB::BaseSerializer::RW_BOOL):
2847         {
2848             if (lua_isboolean(_lua, pos))
2849             {
2850                 ssp->set(static_cast<bool>(lua_toboolean(_lua, pos)!=0));
2851                 return 0;
2852             }
2853             else if (lua_isnumber(_lua, pos))
2854             {
2855                 ssp->set(static_cast<bool>(lua_tonumber(_lua, pos)!=0));
2856                 return 0;
2857             }
2858             break;
2859         }
2860         case(osgDB::BaseSerializer::RW_STRING):
2861         {
2862             if (lua_isstring(_lua, pos))
2863             {
2864                 ssp->set(std::string(lua_tostring(_lua, pos)));
2865                 return 0;
2866             }
2867             break;
2868         }
2869         case(osgDB::BaseSerializer::RW_GLENUM):
2870         {
2871             if (lua_isnumber(_lua, pos))
2872             {
2873                 ssp->set(static_cast<GLenum>(lua_tonumber(_lua, pos)));
2874                 return 0;
2875             }
2876             else if (lua_isstring(_lua, pos))
2877             {
2878                 const char* enumString = lua_tostring(_lua, pos);
2879                 GLenum value = lookUpGLenumValue(enumString); //getValue("GL",enumString);
2880 
2881                 ssp->set(value);
2882                 return 0;
2883             }
2884             OSG_NOTICE<<"LuaScriptEngine::getDataFromStack() osgDB::BaseSerializer::RW_GLENUM Failed"<<std::endl;
2885             break;
2886         }
2887         case(osgDB::BaseSerializer::RW_ENUM):
2888         {
2889             if (lua_isnumber(_lua, pos))
2890             {
2891                 ssp->set(static_cast<int>(lua_tonumber(_lua, pos)));
2892                 return 0;
2893             }
2894             else if (lua_isstring(_lua, pos))
2895             {
2896                 OSG_NOTICE<<"LuaScriptEngine::getDataFromStack() osgDB::BaseSerializer::RW_ENUM Failed to convert string"<<std::endl;
2897                 return 0;
2898             }
2899             break;
2900         }
2901         case(osgDB::BaseSerializer::RW_SHORT):
2902         {
2903             if (lua_isnumber(_lua, pos))
2904             {
2905                 ssp->set(static_cast<short>(lua_tonumber(_lua, pos)));
2906                 return 0;
2907             }
2908             break;
2909         }
2910         case(osgDB::BaseSerializer::RW_USHORT):
2911         {
2912             if (lua_isnumber(_lua, pos))
2913             {
2914                 ssp->set(static_cast<unsigned short>(lua_tonumber(_lua, pos)));
2915                 return 0;
2916             }
2917             break;
2918         }
2919         case(osgDB::BaseSerializer::RW_INT):
2920         {
2921             if (lua_isnumber(_lua, pos))
2922             {
2923                 ssp->set(static_cast<int>(lua_tonumber(_lua, pos)));
2924                 return 0;
2925             }
2926             break;
2927         }
2928         case(osgDB::BaseSerializer::RW_UINT):
2929         {
2930             if (lua_isnumber(_lua, pos))
2931             {
2932                 ssp->set(static_cast<unsigned int>(lua_tonumber(_lua, pos)));
2933                 return 0;
2934             }
2935             break;
2936         }
2937         case(osgDB::BaseSerializer::RW_FLOAT):
2938         {
2939             if (lua_isnumber(_lua, pos))
2940             {
2941                 ssp->set(static_cast<float>(lua_tonumber(_lua, pos)));
2942                 return 0;
2943             }
2944             break;
2945         }
2946         case(osgDB::BaseSerializer::RW_DOUBLE):
2947         {
2948             if (lua_isnumber(_lua, pos))
2949             {
2950                 ssp->set(static_cast<double>(lua_tonumber(_lua, pos)));
2951                 return 0;
2952             }
2953             break;
2954         }
2955 
2956         case(osgDB::BaseSerializer::RW_VEC2B): if (getDataFromStack<osg::Vec2b>(ssp, pos)) return 0; break;
2957         case(osgDB::BaseSerializer::RW_VEC3B): if (getDataFromStack<osg::Vec3b>(ssp, pos)) return 0; break;
2958         case(osgDB::BaseSerializer::RW_VEC4B): if (getDataFromStack<osg::Vec4b>(ssp, pos)) return 0; break;
2959 
2960         case(osgDB::BaseSerializer::RW_VEC2UB): if (getDataFromStack<osg::Vec2ub>(ssp, pos)) return 0; break;
2961         case(osgDB::BaseSerializer::RW_VEC3UB): if (getDataFromStack<osg::Vec3ub>(ssp, pos)) return 0; break;
2962         case(osgDB::BaseSerializer::RW_VEC4UB): if (getDataFromStack<osg::Vec4ub>(ssp, pos)) return 0; break;
2963 
2964         case(osgDB::BaseSerializer::RW_VEC2S): if (getDataFromStack<osg::Vec2s>(ssp, pos)) return 0; break;
2965         case(osgDB::BaseSerializer::RW_VEC3S): if (getDataFromStack<osg::Vec3s>(ssp, pos)) return 0; break;
2966         case(osgDB::BaseSerializer::RW_VEC4S): if (getDataFromStack<osg::Vec4s>(ssp, pos)) return 0; break;
2967 
2968         case(osgDB::BaseSerializer::RW_VEC2US): if (getDataFromStack<osg::Vec2us>(ssp, pos)) return 0; break;
2969         case(osgDB::BaseSerializer::RW_VEC3US): if (getDataFromStack<osg::Vec3us>(ssp, pos)) return 0; break;
2970         case(osgDB::BaseSerializer::RW_VEC4US): if (getDataFromStack<osg::Vec4us>(ssp, pos)) return 0; break;
2971 
2972         case(osgDB::BaseSerializer::RW_VEC2I): if (getDataFromStack<osg::Vec2i>(ssp, pos)) return 0; break;
2973         case(osgDB::BaseSerializer::RW_VEC3I): if (getDataFromStack<osg::Vec3i>(ssp, pos)) return 0; break;
2974         case(osgDB::BaseSerializer::RW_VEC4I): if (getDataFromStack<osg::Vec4i>(ssp, pos)) return 0; break;
2975 
2976         case(osgDB::BaseSerializer::RW_VEC2UI): if (getDataFromStack<osg::Vec2ui>(ssp, pos)) return 0; break;
2977         case(osgDB::BaseSerializer::RW_VEC3UI): if (getDataFromStack<osg::Vec3ui>(ssp, pos)) return 0; break;
2978         case(osgDB::BaseSerializer::RW_VEC4UI): if (getDataFromStack<osg::Vec4ui>(ssp, pos)) return 0; break;
2979 
2980         case(osgDB::BaseSerializer::RW_VEC2F): if (getDataFromStack<osg::Vec2f>(ssp, pos)) return 0; break;
2981         case(osgDB::BaseSerializer::RW_VEC3F): if (getDataFromStack<osg::Vec3f>(ssp, pos)) return 0; break;
2982         case(osgDB::BaseSerializer::RW_VEC4F): if (getDataFromStack<osg::Vec4f>(ssp, pos)) return 0; break;
2983 
2984         case(osgDB::BaseSerializer::RW_VEC2D): if (getDataFromStack<osg::Vec2d>(ssp, pos)) return 0; break;
2985         case(osgDB::BaseSerializer::RW_VEC3D): if (getDataFromStack<osg::Vec3d>(ssp, pos)) return 0; break;
2986         case(osgDB::BaseSerializer::RW_VEC4D): if (getDataFromStack<osg::Vec4d>(ssp, pos)) return 0; break;
2987 
2988         case(osgDB::BaseSerializer::RW_QUAT): if (getDataFromStack<osg::Quat>(ssp, pos)) return 0; break;
2989         case(osgDB::BaseSerializer::RW_PLANE): if (getDataFromStack<osg::Plane>(ssp, pos)) return 0; break;
2990 
2991         #ifdef OSG_USE_FLOAT_MATRIX
2992         case(osgDB::BaseSerializer::RW_MATRIX):
2993 #endif
2994         case(osgDB::BaseSerializer::RW_MATRIXF):
2995         {
2996             osg::Matrixd value;
2997             if (getValue(pos, value))
2998             {
2999                 ssp->set(value);
3000                 return 0;
3001             }
3002             break;
3003         }
3004 #ifndef OSG_USE_FLOAT_MATRIX
3005         case(osgDB::BaseSerializer::RW_MATRIX):
3006 #endif
3007         case(osgDB::BaseSerializer::RW_MATRIXD):
3008         {
3009             osg::Matrixd value;
3010             if (getValue(pos, value))
3011             {
3012                 ssp->set(value);
3013                 return 0;
3014             }
3015             break;
3016         }
3017         case(osgDB::BaseSerializer::RW_BOUNDINGBOXF):
3018         {
3019             osg::BoundingBoxf value;
3020             if (getValue(pos, value))
3021             {
3022                 ssp->set(value);
3023                 return 0;
3024             }
3025             break;
3026         }
3027         case(osgDB::BaseSerializer::RW_BOUNDINGBOXD):
3028         {
3029             osg::BoundingBoxd value;
3030             if (getValue(pos, value))
3031             {
3032                 ssp->set(value);
3033                 return 0;
3034             }
3035             break;
3036         }
3037         case(osgDB::BaseSerializer::RW_BOUNDINGSPHEREF):
3038         {
3039             osg::BoundingSpheref value;
3040             if (getValue(pos, value))
3041             {
3042                 ssp->set(value);
3043                 return 0;
3044             }
3045             break;
3046         }
3047         case(osgDB::BaseSerializer::RW_BOUNDINGSPHERED):
3048         {
3049             osg::BoundingSphered value;
3050             if (getValue(pos, value))
3051             {
3052                 ssp->set(value);
3053                 return 0;
3054             }
3055             break;
3056         }
3057         case(osgDB::BaseSerializer::RW_LIST):
3058         {
3059             OSG_NOTICE<<"Need to implement RW_LIST support"<<std::endl;
3060             break;
3061         }
3062         case(osgDB::BaseSerializer::RW_IMAGE):
3063         case(osgDB::BaseSerializer::RW_OBJECT):
3064         {
3065             if (lua_istable(_lua, pos))
3066             {
3067                 osg::Object* value = 0;
3068                 lua_pushstring(_lua, "object_ptr");
3069                 lua_rawget(_lua, pos);
3070                 if (lua_type(_lua, -1)==LUA_TUSERDATA) value = *const_cast<osg::Object**>(reinterpret_cast<const osg::Object**>(lua_touserdata(_lua,-1)));
3071                 lua_pop(_lua, 1);
3072 
3073                 if (value)
3074                 {
3075                     ssp->set(value);
3076                     return 0;
3077                 }
3078                 else
3079                 {
3080                     OSG_NOTICE<<"Error: lua type '"<<lua_typename(_lua,lua_type(_lua, pos))<<"' cannot be assigned." <<std::endl;
3081                 }
3082             }
3083             else if (lua_isnil(_lua, pos))
3084             {
3085                 OSG_NOTICE<<"Assigning property object (nil) to to object"<<std::endl;
3086                 osg::Object* value = 0;
3087                 ssp->set(value);
3088                 return 0;
3089             }
3090             else
3091             {
3092                 OSG_NOTICE<<"Error: lua type '"<<lua_typename(_lua,lua_type(_lua, pos))<<"' cannot be assigned."<<std::endl;
3093                 return 0;
3094             }
3095             break;
3096         }
3097         default:
3098             break;
3099     }
3100     OSG_NOTICE<<"LuaScriptEngine::getDataFromStack() property of type = "<<_ci.getTypeName(type)<<" not matched"<<std::endl;
3101     return 0;
3102 
3103 }
3104 
3105 
setPropertyFromStack(osg::Object * object,const std::string & propertyName) const3106 int LuaScriptEngine::setPropertyFromStack(osg::Object* object, const std::string& propertyName) const
3107 {
3108     osgDB::BaseSerializer::Type type;
3109     if (!_ci.getPropertyType(object, propertyName, type))
3110     {
3111         if (lua_type(_lua,-1)==LUA_TFUNCTION)
3112         {
3113             int ref = luaL_ref(_lua, LUA_REGISTRYINDEX);
3114             osg::ref_ptr<LuaCallbackObject> lco = new LuaCallbackObject(propertyName, this, ref);
3115 
3116             osg::UserDataContainer* udc = object->getOrCreateUserDataContainer();
3117             unsigned int objectIndex = udc->getUserObjectIndex(propertyName);
3118             if (objectIndex < udc->getNumUserObjects())
3119             {
3120                 udc->setUserObject(objectIndex, lco.get());
3121             }
3122             else
3123             {
3124                 udc->addUserObject(lco.get());
3125             }
3126 
3127             return 0;
3128         }
3129 
3130         type = LuaScriptEngine::getType(-1);
3131     }
3132 
3133     return setPropertyFromStack(object, propertyName, type);
3134 }
3135 
setPropertyFromStack(osg::Object * object,const std::string & propertyName,osgDB::BaseSerializer::Type type) const3136 int LuaScriptEngine::setPropertyFromStack(osg::Object* object, const std::string& propertyName, osgDB::BaseSerializer::Type type) const
3137 {
3138     switch(type)
3139     {
3140         case(osgDB::BaseSerializer::RW_BOOL):
3141         {
3142             if (lua_isboolean(_lua, -1))
3143             {
3144                 _ci.setProperty(object, propertyName, static_cast<bool>(lua_toboolean(_lua, -1)!=0));
3145                 return 0;
3146             }
3147             else if (lua_isnumber(_lua, -1))
3148             {
3149                 _ci.setProperty(object, propertyName, static_cast<bool>(lua_tonumber(_lua, -1)!=0));
3150                 return 0;
3151             }
3152             break;
3153         }
3154         case(osgDB::BaseSerializer::RW_STRING):
3155         {
3156             if (lua_isstring(_lua, -1))
3157             {
3158                 _ci.setProperty(object, propertyName, std::string(lua_tostring(_lua, -1)));
3159                 return 0;
3160             }
3161             break;
3162         }
3163         case(osgDB::BaseSerializer::RW_GLENUM):
3164         {
3165             if (lua_isnumber(_lua, -1))
3166             {
3167                 _ci.setProperty(object, propertyName, static_cast<GLenum>(lua_tonumber(_lua, -1)));
3168                 return 0;
3169             }
3170             else if (lua_isstring(_lua, -1))
3171             {
3172                 const char* enumString = lua_tostring(_lua, -1);
3173                 GLenum value = lookUpGLenumValue(enumString); //getValue("GL",enumString);
3174 
3175                 _ci.setProperty(object, propertyName, value);
3176                 return 0;
3177             }
3178             OSG_NOTICE<<"LuaScriptEngine::setPropertyFromStack("<<propertyName<<") osgDB::BaseSerializer::RW_GLENUM Failed"<<std::endl;
3179             break;
3180         }
3181         case(osgDB::BaseSerializer::RW_ENUM):
3182         {
3183             if (lua_isnumber(_lua, -1))
3184             {
3185                 _ci.setProperty(object, propertyName, static_cast<int>(lua_tonumber(_lua, -1)));
3186                 return 0;
3187             }
3188             else if (lua_isstring(_lua, -1))
3189             {
3190                 const char* enumString = lua_tostring(_lua, -1);
3191                 osgDB::BaseSerializer* serializer = _ci.getSerializer(object, propertyName, type);
3192                 osgDB::IntLookup* lookup = serializer ? serializer->getIntLookup() : 0;
3193                 if (lookup)
3194                 {
3195                     int value = lookup->getValue(enumString);
3196                     _ci.setProperty(object, propertyName, value);
3197                 }
3198                 return 0;
3199             }
3200             break;
3201         }
3202         case(osgDB::BaseSerializer::RW_SHORT):
3203         {
3204             if (lua_isnumber(_lua, -1))
3205             {
3206                 _ci.setProperty(object, propertyName, static_cast<short>(lua_tonumber(_lua, -1)));
3207                 return 0;
3208             }
3209             break;
3210         }
3211         case(osgDB::BaseSerializer::RW_USHORT):
3212         {
3213             if (lua_isnumber(_lua, -1))
3214             {
3215                 _ci.setProperty(object, propertyName, static_cast<unsigned short>(lua_tonumber(_lua, -1)));
3216                 return 0;
3217             }
3218             break;
3219         }
3220         case(osgDB::BaseSerializer::RW_INT):
3221         {
3222             if (lua_isnumber(_lua, -1))
3223             {
3224                 _ci.setProperty(object, propertyName, static_cast<int>(lua_tonumber(_lua, -1)));
3225                 return 0;
3226             }
3227             break;
3228         }
3229         case(osgDB::BaseSerializer::RW_UINT):
3230         {
3231             if (lua_isnumber(_lua, -1))
3232             {
3233                 _ci.setProperty(object, propertyName, static_cast<unsigned int>(lua_tonumber(_lua, -1)));
3234                 return 0;
3235             }
3236             break;
3237         }
3238         case(osgDB::BaseSerializer::RW_FLOAT):
3239         {
3240             if (lua_isnumber(_lua, -1))
3241             {
3242                 _ci.setProperty(object, propertyName, static_cast<float>(lua_tonumber(_lua, -1)));
3243                 return 0;
3244             }
3245             break;
3246         }
3247         case(osgDB::BaseSerializer::RW_DOUBLE):
3248         {
3249             if (lua_isnumber(_lua, -1))
3250             {
3251                 _ci.setProperty(object, propertyName, static_cast<double>(lua_tonumber(_lua, -1)));
3252                 return 0;
3253             }
3254             break;
3255         }
3256 
3257         case(osgDB::BaseSerializer::RW_VEC2B): if (getValueAndSetProperty<osg::Vec2b>(object, propertyName)) return 0; break;
3258         case(osgDB::BaseSerializer::RW_VEC3B): if (getValueAndSetProperty<osg::Vec3b>(object, propertyName)) return 0; break;
3259         case(osgDB::BaseSerializer::RW_VEC4B): if (getValueAndSetProperty<osg::Vec4b>(object, propertyName)) return 0; break;
3260 
3261         case(osgDB::BaseSerializer::RW_VEC2UB): if (getValueAndSetProperty<osg::Vec2ub>(object, propertyName)) return 0; break;
3262         case(osgDB::BaseSerializer::RW_VEC3UB): if (getValueAndSetProperty<osg::Vec3ub>(object, propertyName)) return 0; break;
3263         case(osgDB::BaseSerializer::RW_VEC4UB): if (getValueAndSetProperty<osg::Vec4ub>(object, propertyName)) return 0; break;
3264 
3265         case(osgDB::BaseSerializer::RW_VEC2F): if (getValueAndSetProperty<osg::Vec2f>(object, propertyName)) return 0; break;
3266         case(osgDB::BaseSerializer::RW_VEC3F): if (getValueAndSetProperty<osg::Vec3f>(object, propertyName)) return 0; break;
3267         case(osgDB::BaseSerializer::RW_VEC4F): if (getValueAndSetProperty<osg::Vec4f>(object, propertyName)) return 0; break;
3268 
3269         case(osgDB::BaseSerializer::RW_VEC2D): if (getValueAndSetProperty<osg::Vec2d>(object, propertyName)) return 0; break;
3270         case(osgDB::BaseSerializer::RW_VEC3D): if (getValueAndSetProperty<osg::Vec3d>(object, propertyName)) return 0; break;
3271         case(osgDB::BaseSerializer::RW_VEC4D): if (getValueAndSetProperty<osg::Vec4d>(object, propertyName)) return 0; break;
3272 
3273         case(osgDB::BaseSerializer::RW_QUAT): if (getValueAndSetProperty<osg::Quat>(object, propertyName)) return 0; break;
3274         case(osgDB::BaseSerializer::RW_PLANE): if (getValueAndSetProperty<osg::Plane>(object, propertyName)) return 0; break;
3275 
3276 #ifdef OSG_USE_FLOAT_MATRIX
3277         case(osgDB::BaseSerializer::RW_MATRIX):
3278 #endif
3279         case(osgDB::BaseSerializer::RW_MATRIXF):
3280         {
3281             osg::Matrixd value;
3282             if (getValue(-1, value))
3283             {
3284                 _ci.setProperty(object, propertyName, value);
3285                 return 0;
3286             }
3287             break;
3288         }
3289 #ifndef OSG_USE_FLOAT_MATRIX
3290         case(osgDB::BaseSerializer::RW_MATRIX):
3291 #endif
3292         case(osgDB::BaseSerializer::RW_MATRIXD):
3293         {
3294             osg::Matrixd value;
3295             if (getValue(-1, value))
3296             {
3297                 _ci.setProperty(object, propertyName, value);
3298                 return 0;
3299             }
3300             break;
3301         }
3302         case(osgDB::BaseSerializer::RW_BOUNDINGBOXF):
3303         {
3304             osg::BoundingBoxf value;
3305             if (getValue(-1, value))
3306             {
3307                 _ci.setProperty(object, propertyName, value);
3308                 return 0;
3309             }
3310             break;
3311         }
3312         case(osgDB::BaseSerializer::RW_BOUNDINGBOXD):
3313         {
3314             osg::BoundingBoxd value;
3315             if (getValue(-1, value))
3316             {
3317                 _ci.setProperty(object, propertyName, value);
3318                 return 0;
3319             }
3320             break;
3321         }
3322         case(osgDB::BaseSerializer::RW_BOUNDINGSPHEREF):
3323         {
3324             osg::BoundingSpheref value;
3325             if (getValue(-1, value))
3326             {
3327                 _ci.setProperty(object, propertyName, value);
3328                 return 0;
3329             }
3330             break;
3331         }
3332         case(osgDB::BaseSerializer::RW_BOUNDINGSPHERED):
3333         {
3334             osg::BoundingSphered value;
3335             if (getValue(-1, value))
3336             {
3337                 _ci.setProperty(object, propertyName, value);
3338                 return 0;
3339             }
3340             break;
3341         }
3342         case(osgDB::BaseSerializer::RW_IMAGE):
3343         case(osgDB::BaseSerializer::RW_OBJECT):
3344         {
3345             if (lua_istable(_lua, -1))
3346             {
3347                 osg::Object* value = 0;
3348                 lua_pushstring(_lua, "object_ptr");
3349                 lua_rawget(_lua, -2);
3350                 if (lua_type(_lua, -1)==LUA_TUSERDATA) value = *const_cast<osg::Object**>(reinterpret_cast<const osg::Object**>(lua_touserdata(_lua,-1)));
3351                 lua_pop(_lua, 1);
3352 
3353                 if (value)
3354                 {
3355                     _ci.setProperty(object, propertyName, value);
3356                     return 0;
3357                 }
3358                 else
3359                 {
3360                     OSG_NOTICE<<"Error: lua type '"<<lua_typename(_lua,lua_type(_lua, -1))<<"' cannot be assigned to "<<object->className()<<"::"<<propertyName<<std::endl;
3361                 }
3362             }
3363             else if (lua_type(_lua,-1)==LUA_TFUNCTION)
3364             {
3365                 int ref = luaL_ref(_lua, LUA_REGISTRYINDEX);
3366                 osg::ref_ptr<LuaCallbackObject> lco = new LuaCallbackObject(propertyName, this, ref);
3367                 osg::Object* value = lco.get();
3368                 _ci.setProperty(object, propertyName, value);
3369 
3370                 return 0;
3371             }
3372             else if (lua_isnil(_lua, -1))
3373             {
3374                 OSG_NOTICE<<"Assigning property object (nil) to to object "<<object->className()<<"::"<<propertyName<<std::endl;
3375                 osg::Object* value = 0;
3376                 _ci.setProperty(object, propertyName, value);
3377                 return 0;
3378             }
3379             else
3380             {
3381                 OSG_NOTICE<<"Error: lua type '"<<lua_typename(_lua,lua_type(_lua, -1))<<"' cannot be assigned to "<<object->className()<<"::"<<propertyName<<std::endl;
3382                 return 0;
3383             }
3384             break;
3385         }
3386         case(osgDB::BaseSerializer::RW_LIST):
3387         default:
3388             break;
3389     }
3390     OSG_NOTICE<<"LuaScriptEngine::setPropertyFromStack("<<object<<", "<<propertyName<<") property of type = "<<_ci.getTypeName(type)<<" not implemented"<<std::endl;
3391     return 0;
3392 }
3393 
3394 
3395 
getfields(int pos,const char * f1,const char * f2,int type) const3396 bool LuaScriptEngine::getfields(int pos, const char* f1, const char* f2, int type) const
3397 {
3398     int abs_pos = getAbsolutePos(pos);
3399     lua_getfield(_lua, abs_pos, f1);
3400     lua_getfield(_lua, abs_pos, f2);
3401     if (lua_type(_lua, -2)!=type || lua_type(_lua, -1)!=type) { lua_pop(_lua, 2); return false; }
3402 
3403     return true;
3404 }
3405 
getfields(int pos,const char * f1,const char * f2,const char * f3,int type) const3406 bool LuaScriptEngine::getfields(int pos, const char* f1, const char* f2, const char* f3, int type) const
3407 {
3408     int abs_pos = getAbsolutePos(pos);
3409     lua_getfield(_lua, abs_pos, f1);
3410     lua_getfield(_lua, abs_pos, f2);
3411     lua_getfield(_lua, abs_pos, f3);
3412     if (lua_type(_lua, -3)!=type || lua_type(_lua, -2)!=type ||
3413         lua_type(_lua, -1)!=type) { lua_pop(_lua, 3); return false; }
3414 
3415     return true;
3416 }
3417 
getfields(int pos,const char * f1,const char * f2,const char * f3,const char * f4,int type) const3418 bool LuaScriptEngine::getfields(int pos, const char* f1, const char* f2, const char* f3, const char* f4, int type) const
3419 {
3420     int abs_pos = getAbsolutePos(pos);
3421     lua_getfield(_lua, abs_pos, f1);
3422     lua_getfield(_lua, abs_pos, f2);
3423     lua_getfield(_lua, abs_pos, f3);
3424     lua_getfield(_lua, abs_pos, f4);
3425     if (lua_type(_lua, -4)!=type || lua_type(_lua, -3)!=type ||
3426         lua_type(_lua, -2)!=type || lua_type(_lua, -1)!=type) { lua_pop(_lua, 4); return false; }
3427 
3428     return true;
3429 }
3430 
getfields(int pos,const char * f1,const char * f2,const char * f3,const char * f4,const char * f5,const char * f6,int type) const3431 bool LuaScriptEngine::getfields(int pos, const char* f1, const char* f2, const char* f3, const char* f4, const char* f5, const char* f6, int type) const
3432 {
3433     int abs_pos = getAbsolutePos(pos);
3434     lua_getfield(_lua, abs_pos, f1);
3435     lua_getfield(_lua, abs_pos, f2);
3436     lua_getfield(_lua, abs_pos, f3);
3437     lua_getfield(_lua, abs_pos, f4);
3438     lua_getfield(_lua, abs_pos, f5);
3439     lua_getfield(_lua, abs_pos, f6);
3440     if (lua_type(_lua, -6)!=type || lua_type(_lua, -5)!=type ||
3441         lua_type(_lua, -4)!=type || lua_type(_lua, -3)!=type ||
3442         lua_type(_lua, -2)!=type || lua_type(_lua, -1)!=type) { lua_pop(_lua, 6); return false; }
3443 
3444     return true;
3445 }
3446 
getelements(int pos,int numElements,int type) const3447 bool LuaScriptEngine::getelements(int pos, int numElements, int type) const
3448 {
3449     int abs_pos = getAbsolutePos(pos);
3450     for(int i=0; i<numElements; ++i)
3451     {
3452         lua_pushinteger(_lua, i);
3453         lua_gettable(_lua, abs_pos);
3454         if (lua_type(_lua, -1)!=type) { lua_pop(_lua, i+1); return false; }
3455     }
3456     return true;
3457 }
3458 
3459 
getType(int pos) const3460 osgDB::BaseSerializer::Type LuaScriptEngine::getType(int pos) const
3461 {
3462     int abs_pos = getAbsolutePos(pos);
3463     switch(lua_type(_lua, abs_pos))
3464     {
3465         case(LUA_TNIL): return osgDB::BaseSerializer::RW_UNDEFINED;
3466         case(LUA_TNUMBER): return osgDB::BaseSerializer::RW_DOUBLE;
3467         case(LUA_TBOOLEAN): return osgDB::BaseSerializer::RW_BOOL;
3468         case(LUA_TSTRING): return osgDB::BaseSerializer::RW_STRING;
3469         case(LUA_TTABLE):
3470         {
3471             lua_pushstring(_lua, "object_ptr");
3472             lua_rawget(_lua, abs_pos);
3473             bool isObject = (lua_type(_lua, -1)==LUA_TUSERDATA);
3474             lua_pop(_lua, 1);
3475 
3476             if (isObject)
3477             {
3478                 return osgDB::BaseSerializer::RW_OBJECT;
3479             }
3480 
3481 
3482             int n = lua_gettop(_lua);    /* number of arguments */
3483             lua_pushnil(_lua);
3484 
3485             int numStringKeys = 0;
3486             int numNumberKeys = 0;
3487             int numNumberFields = 0;
3488 
3489             while (lua_next(_lua, n) != 0)
3490             {
3491                 if (lua_type(_lua, -2)==LUA_TSTRING) ++numStringKeys;
3492                 else if (lua_type(_lua, -2)==LUA_TNUMBER) ++numNumberKeys;
3493 
3494                 if (lua_type(_lua, -1)==LUA_TNUMBER) ++numNumberFields;
3495 
3496                 lua_pop(_lua, 1); // remove value, leave key for next iteration
3497             }
3498 
3499             if ((numStringKeys==2 || numNumberKeys==2) && (numNumberFields==2))
3500             {
3501                 return osgDB::BaseSerializer::RW_VEC2D;
3502             }
3503             else if ((numStringKeys==3 || numNumberKeys==3) && (numNumberFields==3))
3504             {
3505                 return osgDB::BaseSerializer::RW_VEC3D;
3506             }
3507             else if ((numStringKeys==4 || numNumberKeys==4) && (numNumberFields==4))
3508             {
3509                 return osgDB::BaseSerializer::RW_VEC4D;
3510             }
3511             else if ((numNumberKeys==16) && (numNumberFields==16))
3512             {
3513                 return osgDB::BaseSerializer::RW_MATRIXD;
3514             }
3515             else if ((numNumberKeys==6) && (numNumberFields==6))
3516             {
3517                 return osgDB::BaseSerializer::RW_BOUNDINGBOXD;
3518             }
3519             // not supported
3520             OSG_NOTICE<<"Warning: LuaScriptEngine::getType() Lua table configuration not supported."<<std::endl;
3521             break;
3522         }
3523         default:
3524             OSG_NOTICE<<"Warning: LuaScriptEngine::getType() Lua type "<<lua_typename(_lua, lua_type(_lua, abs_pos))<<" not supported."<<std::endl;
3525             break;
3526 
3527     }
3528     return osgDB::BaseSerializer::RW_UNDEFINED;
3529 }
3530 
getvec2(int pos) const3531 bool LuaScriptEngine::getvec2(int pos) const
3532 {
3533     int abs_pos = getAbsolutePos(pos);
3534     if (lua_istable(_lua, abs_pos))
3535     {
3536         if (getfields(abs_pos, "x", "y", LUA_TNUMBER) ||
3537             getfields(abs_pos, "s", "t", LUA_TNUMBER) ||
3538             getfields(abs_pos, "luminance", "alpha", LUA_TNUMBER) ||
3539             getelements(abs_pos, 2, LUA_TNUMBER))
3540         {
3541             return true;
3542         }
3543     }
3544     return false;
3545 }
3546 
getvec3(int pos) const3547 bool LuaScriptEngine::getvec3(int pos) const
3548 {
3549     int abs_pos = getAbsolutePos(pos);
3550     if (lua_istable(_lua, abs_pos))
3551     {
3552         if (getfields(abs_pos, "x", "y", "z", LUA_TNUMBER) ||
3553             getfields(abs_pos, "r", "g", "b", LUA_TNUMBER) ||
3554             getfields(abs_pos, "red", "green", "blue", LUA_TNUMBER) ||
3555             getfields(abs_pos, "s", "t", "r", LUA_TNUMBER) ||
3556             getelements(abs_pos, 3, LUA_TNUMBER))
3557         {
3558             return true;
3559         }
3560     }
3561     return false;
3562 }
getvec4(int pos) const3563 bool LuaScriptEngine::getvec4(int pos) const
3564 {
3565     int abs_pos = getAbsolutePos(pos);
3566     if (lua_istable(_lua, abs_pos))
3567     {
3568         if (getfields(abs_pos, "x", "y", "z", "w", LUA_TNUMBER) ||
3569             getfields(abs_pos, "r", "g", "b", "a", LUA_TNUMBER) ||
3570             getfields(abs_pos, "red", "green", "blue", "alpha", LUA_TNUMBER) ||
3571             getfields(abs_pos, "s", "t", "r", "q", LUA_TNUMBER) ||
3572             getelements(abs_pos, 4, LUA_TNUMBER))
3573         {
3574             return true;
3575         }
3576     }
3577     return false;
3578 }
3579 
getmatrix(int pos) const3580 bool LuaScriptEngine::getmatrix(int pos) const
3581 {
3582     int abs_pos = getAbsolutePos(pos);
3583     if (lua_istable(_lua, abs_pos))
3584     {
3585         if (getelements(abs_pos, 16,LUA_TNUMBER))
3586         {
3587             return true;
3588         }
3589     }
3590     return false;
3591 }
3592 
getboundingbox(int pos) const3593 bool LuaScriptEngine::getboundingbox(int pos) const
3594 {
3595     int abs_pos = getAbsolutePos(pos);
3596     if (lua_istable(_lua, abs_pos))
3597     {
3598         if (getfields(abs_pos, "xMin", "yMin", "zMin", "xMax", "yMax", "zMax", LUA_TNUMBER) ||
3599             getelements(abs_pos, 6, LUA_TNUMBER))
3600         {
3601             return true;
3602         }
3603     }
3604     return false;
3605 }
3606 
getboundingsphere(int pos) const3607 bool LuaScriptEngine::getboundingsphere(int pos) const
3608 {
3609     int abs_pos = getAbsolutePos(pos);
3610     if (lua_istable(_lua, abs_pos))
3611     {
3612         if (getfields(abs_pos, "x", "y", "z", "radius", LUA_TNUMBER) ||
3613             getelements(abs_pos, 4, LUA_TNUMBER))
3614         {
3615             return true;
3616         }
3617     }
3618     return false;
3619 }
3620 
getValue(int pos,osg::Matrixf & value) const3621 bool LuaScriptEngine::getValue(int pos, osg::Matrixf& value) const
3622 {
3623     if (!getmatrix(pos)) return false;
3624 
3625     for(int r=0; r<4; ++r)
3626     {
3627         for(int c=0; c<4; ++c)
3628         {
3629             value(r,c) = lua_tonumber(_lua, -16+(r*4+c));
3630         }
3631     }
3632     lua_pop(_lua, 16);
3633     return true;
3634 }
3635 
getValue(int pos,osg::Matrixd & value) const3636 bool LuaScriptEngine::getValue(int pos, osg::Matrixd& value) const
3637 {
3638     if (!getmatrix(pos)) return false;
3639 
3640     for(int r=0; r<4; ++r)
3641     {
3642         for(int c=0; c<4; ++c)
3643         {
3644             value(r,c) = lua_tonumber(_lua, -16+(r*4+c));
3645         }
3646     }
3647     lua_pop(_lua, 16);
3648     return true;
3649 }
3650 
getValue(int pos,osg::BoundingBoxf & value) const3651 bool LuaScriptEngine::getValue(int pos, osg::BoundingBoxf& value) const
3652 {
3653     if (!getboundingbox(pos)) return false;
3654     value.set(lua_tonumber(_lua, -6), lua_tonumber(_lua, -5), lua_tonumber(_lua, -4), lua_tonumber(_lua, -3), lua_tonumber(_lua, -2), lua_tonumber(_lua, -1));
3655     lua_pop(_lua, 6);
3656     return true;
3657 }
3658 
getValue(int pos,osg::BoundingBoxd & value) const3659 bool LuaScriptEngine::getValue(int pos, osg::BoundingBoxd& value) const
3660 {
3661     if (!getboundingbox(pos)) return false;
3662     value.set(lua_tonumber(_lua, -6), lua_tonumber(_lua, -5), lua_tonumber(_lua, -4), lua_tonumber(_lua, -3), lua_tonumber(_lua, -2), lua_tonumber(_lua, -1));
3663     lua_pop(_lua, 6);
3664     return true;
3665 }
3666 
getValue(int pos,osg::BoundingSpheref & value) const3667 bool LuaScriptEngine::getValue(int pos, osg::BoundingSpheref& value) const
3668 {
3669     if (!getboundingsphere(pos)) return false;
3670     value.set(osg::Vec3f(lua_tonumber(_lua, -4), lua_tonumber(_lua, -3), lua_tonumber(_lua, -2)), lua_tonumber(_lua, -1));
3671     lua_pop(_lua, 4);
3672     return true;
3673 }
3674 
getValue(int pos,osg::BoundingSphered & value) const3675 bool LuaScriptEngine::getValue(int pos, osg::BoundingSphered& value) const
3676 {
3677     if (!getboundingsphere(pos)) return false;
3678     value.set(osg::Vec3d(lua_tonumber(_lua, -4), lua_tonumber(_lua, -3), lua_tonumber(_lua, -2)), lua_tonumber(_lua, -1));
3679     lua_pop(_lua, 4);
3680     return true;
3681 }
3682 
pushValue(const osg::Matrixf & value) const3683 void LuaScriptEngine::pushValue(const osg::Matrixf& value) const
3684 {
3685     lua_newtable(_lua);
3686     lua_newtable(_lua); luaL_getmetatable(_lua, "LuaScriptEngine.Table"); lua_setmetatable(_lua, -2);
3687 
3688     for(unsigned int r=0; r<4; ++r)
3689     {
3690         for(unsigned int c=0; c<4; ++c)
3691         {
3692             lua_pushinteger(_lua, r*4+c); lua_pushnumber(_lua, (lua_Integer) value(r,c)); lua_settable(_lua, -3);
3693         }
3694     }
3695 }
3696 
pushValue(const osg::Matrixd & value) const3697 void LuaScriptEngine::pushValue(const osg::Matrixd& value) const
3698 {
3699     lua_newtable(_lua);
3700     lua_newtable(_lua); luaL_getmetatable(_lua, "LuaScriptEngine.Table"); lua_setmetatable(_lua, -2);
3701 
3702     for(unsigned int r=0; r<4; ++r)
3703     {
3704         for(unsigned int c=0; c<4; ++c)
3705         {
3706             lua_pushinteger(_lua, r*4+c); lua_pushnumber(_lua, value(r,c)); lua_settable(_lua, -3);
3707         }
3708     }
3709 }
3710 
pushValue(const osg::BoundingBoxf & value) const3711 void LuaScriptEngine::pushValue(const osg::BoundingBoxf& value) const
3712 {
3713     lua_newtable(_lua);
3714     lua_newtable(_lua); luaL_getmetatable(_lua, "LuaScriptEngine.Table"); lua_setmetatable(_lua, -2);
3715     lua_pushstring(_lua, "xMin"); lua_pushnumber(_lua, value.xMin()); lua_settable(_lua, -3);
3716     lua_pushstring(_lua, "yMin"); lua_pushnumber(_lua, value.yMin()); lua_settable(_lua, -3);
3717     lua_pushstring(_lua, "zMin"); lua_pushnumber(_lua, value.zMin()); lua_settable(_lua, -3);
3718     lua_pushstring(_lua, "xMax"); lua_pushnumber(_lua, value.xMax()); lua_settable(_lua, -3);
3719     lua_pushstring(_lua, "yMax"); lua_pushnumber(_lua, value.yMax()); lua_settable(_lua, -3);
3720     lua_pushstring(_lua, "zMax"); lua_pushnumber(_lua, value.zMax()); lua_settable(_lua, -3);
3721 }
3722 
pushValue(const osg::BoundingBoxd & value) const3723 void LuaScriptEngine::pushValue(const osg::BoundingBoxd& value) const
3724 {
3725     lua_newtable(_lua);
3726     lua_newtable(_lua); luaL_getmetatable(_lua, "LuaScriptEngine.Table"); lua_setmetatable(_lua, -2);
3727     lua_pushstring(_lua, "xMin"); lua_pushnumber(_lua, value.xMin()); lua_settable(_lua, -3);
3728     lua_pushstring(_lua, "yMin"); lua_pushnumber(_lua, value.yMin()); lua_settable(_lua, -3);
3729     lua_pushstring(_lua, "zMin"); lua_pushnumber(_lua, value.zMin()); lua_settable(_lua, -3);
3730     lua_pushstring(_lua, "xMax"); lua_pushnumber(_lua, value.xMax()); lua_settable(_lua, -3);
3731     lua_pushstring(_lua, "yMax"); lua_pushnumber(_lua, value.yMax()); lua_settable(_lua, -3);
3732     lua_pushstring(_lua, "zMax"); lua_pushnumber(_lua, value.zMax()); lua_settable(_lua, -3);
3733 }
3734 
pushValue(const osg::BoundingSpheref & value) const3735 void LuaScriptEngine::pushValue(const osg::BoundingSpheref& value) const
3736 {
3737     lua_newtable(_lua);
3738     lua_newtable(_lua); luaL_getmetatable(_lua, "LuaScriptEngine.Table"); lua_setmetatable(_lua, -2);
3739     lua_pushstring(_lua, "x"); lua_pushnumber(_lua, value.center().x()); lua_settable(_lua, -3);
3740     lua_pushstring(_lua, "y"); lua_pushnumber(_lua, value.center().y()); lua_settable(_lua, -3);
3741     lua_pushstring(_lua, "z"); lua_pushnumber(_lua, value.center().z()); lua_settable(_lua, -3);
3742     lua_pushstring(_lua, "radius"); lua_pushnumber(_lua, value.radius()); lua_settable(_lua, -3);
3743 }
3744 
pushValue(const osg::BoundingSphered & value) const3745 void LuaScriptEngine::pushValue(const osg::BoundingSphered& value) const
3746 {
3747     lua_newtable(_lua);
3748     lua_newtable(_lua); luaL_getmetatable(_lua, "LuaScriptEngine.Table"); lua_setmetatable(_lua, -2);
3749     lua_pushstring(_lua, "x"); lua_pushnumber(_lua, value.center().x()); lua_settable(_lua, -3);
3750     lua_pushstring(_lua, "y"); lua_pushnumber(_lua, value.center().y()); lua_settable(_lua, -3);
3751     lua_pushstring(_lua, "z"); lua_pushnumber(_lua, value.center().z()); lua_settable(_lua, -3);
3752     lua_pushstring(_lua, "radius"); lua_pushnumber(_lua, value.radius()); lua_settable(_lua, -3);
3753 }
3754 
pushParameter(osg::Object * object) const3755 bool LuaScriptEngine::pushParameter(osg::Object* object) const
3756 {
3757     osg::ValueObject* vo = dynamic_cast<osg::ValueObject*>(object);
3758     if (vo)
3759     {
3760         PushStackValueVisitor pvv(this);
3761         vo->get(pvv);
3762     }
3763     else
3764     {
3765         pushObject( object);
3766     }
3767 
3768     return false;
3769 }
3770 
popParameter(osg::Object * object) const3771 bool LuaScriptEngine::popParameter(osg::Object* object) const
3772 {
3773     osg::ValueObject* vo = dynamic_cast<osg::ValueObject*>(object);
3774     if (vo)
3775     {
3776         GetStackValueVisitor pvv(this, -1);
3777         vo->set(pvv);
3778         lua_pop(_lua, pvv._numberToPop);
3779     }
3780     else
3781     {
3782         lua_pop(_lua, 1);
3783     }
3784 
3785     return false;
3786 }
3787 
popParameterObject() const3788 osg::Object* LuaScriptEngine::popParameterObject() const
3789 {
3790     osg::ref_ptr<osg::Object> object = 0;
3791 
3792     osgDB::BaseSerializer::Type type = getType(-1);
3793     switch(type)
3794     {
3795         case(osgDB::BaseSerializer::RW_BOOL):
3796         {
3797             if (lua_isboolean(_lua, -1)) object = new osg::BoolValueObject("", lua_toboolean(_lua, -1)!=0);
3798             break;
3799         }
3800         case(osgDB::BaseSerializer::RW_STRING):
3801         {
3802             if (lua_isstring(_lua, -1)) object = new osg::StringValueObject("", lua_tostring(_lua, -1));
3803             break;
3804         }
3805         case(osgDB::BaseSerializer::RW_GLENUM):
3806         case(osgDB::BaseSerializer::RW_ENUM):
3807             if (lua_isstring(_lua, -1))
3808             {
3809                 object = new osg::StringValueObject("", lua_tostring(_lua, -1));
3810             }
3811             else if (lua_isnumber(_lua, -1))
3812             {
3813                 object = new osg::IntValueObject("", static_cast<int>(lua_tonumber(_lua, -1)));
3814             }
3815             break;
3816         case(osgDB::BaseSerializer::RW_INT):
3817         {
3818             if (lua_isnumber(_lua, -1)) object = new osg::IntValueObject("", static_cast<int>(lua_tonumber(_lua, -1)));
3819             break;
3820         }
3821         case(osgDB::BaseSerializer::RW_UINT):
3822         {
3823             if (lua_isnumber(_lua, -1)) object = new osg::UIntValueObject("", static_cast<unsigned int>(lua_tonumber(_lua, -1)));
3824             break;
3825         }
3826         case(osgDB::BaseSerializer::RW_FLOAT):
3827         {
3828             if (lua_isnumber(_lua, -1)) object = new osg::FloatValueObject("", static_cast<float>(lua_tonumber(_lua, -1)));
3829             break;
3830         }
3831         case(osgDB::BaseSerializer::RW_DOUBLE):
3832         {
3833             if (lua_isnumber(_lua, -1)) object = new osg::DoubleValueObject("", static_cast<double>(lua_tonumber(_lua, -1)));
3834             break;
3835         }
3836 
3837         case(osgDB::BaseSerializer::RW_VEC2B): object = getValueObject<osg::Vec2b>(-1); break;
3838         case(osgDB::BaseSerializer::RW_VEC3B): object = getValueObject<osg::Vec3b>(-1); break;
3839         case(osgDB::BaseSerializer::RW_VEC4B): object = getValueObject<osg::Vec4b>(-1); break;
3840 
3841         case(osgDB::BaseSerializer::RW_VEC2UB): object = getValueObject<osg::Vec2ub>(-1); break;
3842         case(osgDB::BaseSerializer::RW_VEC3UB): object = getValueObject<osg::Vec3ub>(-1); break;
3843         case(osgDB::BaseSerializer::RW_VEC4UB): object = getValueObject<osg::Vec4ub>(-1); break;
3844 
3845         case(osgDB::BaseSerializer::RW_VEC2S): object = getValueObject<osg::Vec2s>(-1); break;
3846         case(osgDB::BaseSerializer::RW_VEC3S): object = getValueObject<osg::Vec3s>(-1); break;
3847         case(osgDB::BaseSerializer::RW_VEC4S): object = getValueObject<osg::Vec4s>(-1); break;
3848 
3849         case(osgDB::BaseSerializer::RW_VEC2US): object = getValueObject<osg::Vec2us>(-1); break;
3850         case(osgDB::BaseSerializer::RW_VEC3US): object = getValueObject<osg::Vec3us>(-1); break;
3851         case(osgDB::BaseSerializer::RW_VEC4US): object = getValueObject<osg::Vec4us>(-1); break;
3852 
3853         case(osgDB::BaseSerializer::RW_VEC2I): object = getValueObject<osg::Vec2i>(-1); break;
3854         case(osgDB::BaseSerializer::RW_VEC3I): object = getValueObject<osg::Vec3i>(-1); break;
3855         case(osgDB::BaseSerializer::RW_VEC4I): object = getValueObject<osg::Vec4i>(-1); break;
3856 
3857         case(osgDB::BaseSerializer::RW_VEC2UI): object = getValueObject<osg::Vec2ui>(-1); break;
3858         case(osgDB::BaseSerializer::RW_VEC3UI): object = getValueObject<osg::Vec3ui>(-1); break;
3859         case(osgDB::BaseSerializer::RW_VEC4UI): object = getValueObject<osg::Vec4ui>(-1); break;
3860 
3861         case(osgDB::BaseSerializer::RW_VEC2F): object = getValueObject<osg::Vec2f>(-1); break;
3862         case(osgDB::BaseSerializer::RW_VEC3F): object = getValueObject<osg::Vec3f>(-1); break;
3863         case(osgDB::BaseSerializer::RW_VEC4F): object = getValueObject<osg::Vec4f>(-1); break;
3864 
3865         case(osgDB::BaseSerializer::RW_VEC2D): object = getValueObject<osg::Vec2d>(-1); break;
3866         case(osgDB::BaseSerializer::RW_VEC3D): object = getValueObject<osg::Vec3d>(-1); break;
3867         case(osgDB::BaseSerializer::RW_VEC4D): object = getValueObject<osg::Vec4d>(-1); break;
3868 
3869         case(osgDB::BaseSerializer::RW_QUAT): object = getValueObject<osg::Quat>(-1); break;
3870         case(osgDB::BaseSerializer::RW_PLANE): object = getValueObject<osg::Plane>(-1); break;
3871 
3872 #ifdef OSG_USE_FLOAT_MATRIX
3873         case(osgDB::BaseSerializer::RW_MATRIX):
3874 #endif
3875         case(osgDB::BaseSerializer::RW_MATRIXF):
3876         {
3877             osg::Matrixf value;
3878             if (getValue(-1, value)) object = new osg::MatrixfValueObject("", value);
3879             break;
3880         }
3881 
3882 #ifndef OSG_USE_FLOAT_MATRIX
3883         case(osgDB::BaseSerializer::RW_MATRIX):
3884 #endif
3885         case(osgDB::BaseSerializer::RW_MATRIXD):
3886         {
3887             osg::Matrixd value;
3888             if (getValue(-1, value)) object = new osg::MatrixdValueObject("", value);
3889             break;
3890         }
3891         case(osgDB::BaseSerializer::RW_BOUNDINGBOXF):
3892         {
3893             osg::BoundingBoxf value;
3894             if (getValue(-1, value)) object = new osg::BoundingBoxfValueObject("", value);
3895             break;
3896         }
3897         case(osgDB::BaseSerializer::RW_BOUNDINGBOXD):
3898         {
3899             osg::BoundingBoxd value;
3900             if (getValue(-1, value)) object = new osg::BoundingBoxdValueObject("", value);
3901             break;
3902         }
3903         case(osgDB::BaseSerializer::RW_BOUNDINGSPHEREF):
3904         {
3905             osg::BoundingSpheref value;
3906             if (getValue(-1, value)) object = new osg::BoundingSpherefValueObject("", value);
3907             break;
3908         }
3909         case(osgDB::BaseSerializer::RW_BOUNDINGSPHERED):
3910         {
3911             osg::BoundingSphered value;
3912             if (getValue(-1, value)) object = new osg::BoundingSpheredValueObject("", value);
3913             break;
3914         }
3915         case(osgDB::BaseSerializer::RW_LIST):
3916         {
3917             OSG_NOTICE<<"Need to implement RW_LIST support"<<std::endl;
3918             break;
3919         }
3920         case(osgDB::BaseSerializer::RW_IMAGE):
3921         case(osgDB::BaseSerializer::RW_OBJECT):
3922         {
3923             lua_pushstring(_lua, "object_ptr");
3924             lua_rawget(_lua, -2);
3925             if (lua_type(_lua, -1)==LUA_TUSERDATA)
3926             {
3927                 object = *const_cast<osg::Object**>(reinterpret_cast<const osg::Object**>(lua_touserdata(_lua,-1)));
3928             }
3929             lua_pop(_lua, 1);
3930         }
3931         default:
3932             break;
3933     }
3934 
3935     lua_pop(_lua, 1);
3936 
3937     return object.release();
3938 }
3939 
pushContainer(osg::Object * object,const std::string & propertyName) const3940 void LuaScriptEngine::pushContainer(osg::Object* object, const std::string& propertyName) const
3941 {
3942     if (object)
3943     {
3944         lua_newtable(_lua);
3945 
3946         // set up objbect_ptr to handle ref/unref of the object
3947         {
3948             lua_pushstring(_lua, "object_ptr");
3949 
3950             // create user data for pointer
3951             void* userdata = lua_newuserdata( _lua, sizeof(osg::Object*));
3952             (*reinterpret_cast<osg::Object**>(userdata)) = object;
3953 
3954             luaL_getmetatable( _lua, "LuaScriptEngine.UnrefObject");
3955             lua_setmetatable( _lua, -2 );
3956 
3957             lua_settable(_lua, -3);
3958 
3959 
3960             // increment the reference count as the lua now will unreference it once it's finished with the userdata for the pointer
3961             object->ref();
3962         }
3963 
3964         lua_pushstring(_lua, "containerPropertyName"); lua_pushstring(_lua, propertyName.c_str()); lua_settable(_lua, -3);
3965 
3966         osgDB::BaseSerializer::Type type;
3967         osgDB::BaseSerializer* bs = _ci.getSerializer(object, propertyName, type);
3968         osgDB::VectorBaseSerializer* vs = dynamic_cast<osgDB::VectorBaseSerializer*>(bs);
3969         osgDB::MapBaseSerializer* ms = dynamic_cast<osgDB::MapBaseSerializer*>(bs);
3970         if (vs)
3971         {
3972             assignClosure("size", getContainerSize);
3973             assignClosure("clear", callVectorClear);
3974             assignClosure("resize", callVectorResize);
3975             assignClosure("reserve", callVectorReserve);
3976             assignClosure("add", callVectorAdd);
3977 
3978             luaL_getmetatable(_lua, "LuaScriptEngine.Container");
3979             lua_setmetatable(_lua, -2);
3980         }
3981         else if (ms)
3982         {
3983             assignClosure("clear", callMapClear);
3984             assignClosure("size", getMapSize);
3985             assignClosure("createIterator", createMapIterator);
3986             assignClosure("createReverseIterator", createMapReverseIterator);
3987 
3988             luaL_getmetatable(_lua, "LuaScriptEngine.Map");
3989             lua_setmetatable(_lua, -2);
3990         }
3991         else
3992         {
3993             OSG_NOTICE<<"Container type not supported."<<std::endl;
3994         }
3995     }
3996     else
3997     {
3998         lua_pushnil(_lua);
3999     }
4000 }
4001 
4002 
createAndPushObject(const std::string & compoundName) const4003 void LuaScriptEngine::createAndPushObject(const std::string& compoundName) const
4004 {
4005     osg::ref_ptr<osg::Object> object = _ci.createObject(compoundName);
4006     if (!object) OSG_NOTICE<<"Failed to create object "<<compoundName<<std::endl;
4007 
4008     pushObject(object.get());
4009 
4010     object.release();
4011 }
4012 
pushObject(osg::Object * object) const4013 void LuaScriptEngine::pushObject(osg::Object* object) const
4014 {
4015     if (object)
4016     {
4017         lua_newtable(_lua);
4018 
4019         // set up objbect_ptr to handle ref/unref of the object
4020         {
4021             lua_pushstring(_lua, "object_ptr");
4022 
4023             // create user data for pointer
4024             void* userdata = lua_newuserdata( _lua, sizeof(osg::Object*));
4025             (*reinterpret_cast<osg::Object**>(userdata)) = object;
4026 
4027             luaL_getmetatable( _lua, "LuaScriptEngine.UnrefObject");
4028             lua_setmetatable( _lua, -2 );
4029 
4030             lua_settable(_lua, -3);
4031 
4032             // increment the reference count as the lua now will unreference it once it's finished with the userdata for the pointer
4033             object->ref();
4034         }
4035 
4036         lua_pushstring(_lua, "libraryName"); lua_pushstring(_lua, object->libraryName()); lua_settable(_lua, -3);
4037         lua_pushstring(_lua, "className"); lua_pushstring(_lua, object->className()); lua_settable(_lua, -3);
4038         lua_pushstring(_lua, "compoundClassName"); lua_pushstring(_lua, object->getCompoundClassName().c_str()); lua_settable(_lua, -3);
4039 
4040         // check to see if Object "is a" vector
4041         osgDB::BaseSerializer::Type type;
4042         osgDB::BaseSerializer* vs = _ci.getSerializer(object, "vector", type);
4043         if (vs)
4044         {
4045             lua_pushstring(_lua, "containerPropertyName"); lua_pushstring(_lua, "vector"); lua_settable(_lua, -3);
4046 
4047             assignClosure("size", getContainerSize);
4048             assignClosure("clear", callVectorClear);
4049             assignClosure("resize", callVectorResize);
4050             assignClosure("reserve", callVectorReserve);
4051             assignClosure("add", callVectorAdd);
4052 
4053             luaL_getmetatable(_lua, "LuaScriptEngine.Container");
4054             lua_setmetatable(_lua, -2);
4055         }
4056         else if (dynamic_cast<osgDB::MapIteratorObject*>(object)!=0)
4057         {
4058             assignClosure("advance", callMapIteratorAdvance);
4059             assignClosure("valid", callMapIteratorValid);
4060             assignClosure("getKey", getMapIteratorKey);
4061             assignClosure("getElement", getMapIteratorElement);
4062             assignClosure("setElement", setMapIteratorElement);
4063         }
4064         else if (dynamic_cast<osg::Image*>(object)!=0)
4065         {
4066             assignClosure("allocate", callImageAllocate);
4067             assignClosure("s", callImageS);
4068             assignClosure("t", callImageT);
4069             assignClosure("r", callImageR);
4070             assignClosure("get", callImageGet);
4071             assignClosure("set", callImageSet);
4072 
4073             luaL_getmetatable(_lua, "LuaScriptEngine.Object");
4074             lua_setmetatable(_lua, -2);
4075         }
4076         else if (dynamic_cast<osg::StateSet*>(object)!=0)
4077         {
4078             assignClosure("add", callStateSetSet);
4079             assignClosure("set", callStateSetSet);
4080             assignClosure("get", callStateSetGet);
4081             assignClosure("remove", callStateSetRemove);
4082 
4083             luaL_getmetatable(_lua, "LuaScriptEngine.Object");
4084             lua_setmetatable(_lua, -2);
4085         }
4086         else if (dynamic_cast<osg::Node*>(object)!=0)
4087         {
4088             assignClosure("getParent", callGetParent);
4089             assignClosure("getNumParents", callGetNumParents);
4090 
4091             luaL_getmetatable(_lua, "LuaScriptEngine.Object");
4092             lua_setmetatable(_lua, -2);
4093         }
4094         else
4095         {
4096             luaL_getmetatable(_lua, "LuaScriptEngine.Object");
4097             lua_setmetatable(_lua, -2);
4098         }
4099     }
4100     else
4101     {
4102         lua_pushnil(_lua);
4103     }
4104 }
4105 
pushAndCastObject(const std::string & compoundClassName,osg::Object * object) const4106 void LuaScriptEngine::pushAndCastObject(const std::string& compoundClassName, osg::Object* object) const
4107 {
4108     if (object && _ci.isObjectOfType(object, compoundClassName))
4109     {
4110         lua_newtable(_lua);
4111 
4112         // set up objbect_ptr to handle ref/unref of the object
4113         {
4114             lua_pushstring(_lua, "object_ptr");
4115 
4116             // create user data for pointer
4117             void* userdata = lua_newuserdata( _lua, sizeof(osg::Object*));
4118             (*reinterpret_cast<osg::Object**>(userdata)) = object;
4119 
4120             luaL_getmetatable( _lua, "LuaScriptEngine.UnrefObject");
4121             lua_setmetatable( _lua, -2 );
4122 
4123             lua_settable(_lua, -3);
4124 
4125             // increment the reference count as the lua now will unreference it once it's finished with the userdata for the pointer
4126             object->ref();
4127         }
4128 
4129         std::string::size_type separator = compoundClassName.find("::");
4130         std::string libraryName = (separator==std::string::npos) ? object->libraryName() : compoundClassName.substr(0, separator);
4131         std::string className = (separator==std::string::npos) ? object->className() : compoundClassName.substr(separator+2,std::string::npos);
4132 
4133         lua_pushstring(_lua, "libraryName"); lua_pushstring(_lua, libraryName.c_str()); lua_settable(_lua, -3);
4134         lua_pushstring(_lua, "className"); lua_pushstring(_lua, className.c_str()); lua_settable(_lua, -3);
4135 
4136         lua_pushstring(_lua, "compoundClassName"); lua_pushstring(_lua, compoundClassName.c_str()); lua_settable(_lua, -3);
4137 
4138         luaL_getmetatable(_lua, "LuaScriptEngine.Object");
4139         lua_setmetatable(_lua, -2);
4140     }
4141     else
4142     {
4143         lua_pushnil(_lua);
4144     }
4145 }
4146 
assignClosure(const char * name,lua_CFunction fn) const4147 void LuaScriptEngine::assignClosure(const char* name, lua_CFunction fn) const
4148 {
4149     lua_pushstring(_lua, name);
4150     lua_pushlightuserdata(_lua, const_cast<LuaScriptEngine*>(this));
4151     lua_pushcclosure(_lua, fn, 1);
4152     lua_settable(_lua, -3);
4153 }
4154 
addPaths(const osgDB::FilePathList & paths)4155 void LuaScriptEngine::addPaths(const osgDB::FilePathList& paths)
4156 {
4157     lua_getglobal( _lua, "package" );
4158 
4159     lua_getfield( _lua, -1, "path" );
4160     std::string  path = lua_tostring( _lua, -1 );
4161     lua_pop( _lua, 1 );
4162 
4163     OSG_INFO<<"LuaScriptEngine::addPaths() original package.path = "<<path<<std::endl;
4164 
4165 
4166     for(osgDB::FilePathList::const_iterator itr = paths.begin();
4167         itr != paths.end();
4168         ++itr)
4169     {
4170         OSG_INFO<<"  Appending path ["<<*itr<<"]"<<std::endl;
4171 
4172         path.append( ";" );
4173         path.append( *itr );
4174         path.append( "/?.lua" );
4175     }
4176 
4177     OSG_INFO<<"   path after = "<<path<<std::endl;
4178 
4179     lua_pushstring( _lua, path.c_str() );
4180     lua_setfield( _lua, -2, "path" );
4181 
4182     lua_pop( _lua, 1 ); // return stack to original
4183 }
4184 
addPaths(const osgDB::Options * options)4185 void LuaScriptEngine::addPaths(const osgDB::Options* options)
4186 {
4187     if (!options) return;
4188     addPaths(options->getDatabasePathList());
4189 }
4190 
4191