/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2013 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include "LuaScriptEngine.h" #include #include using namespace lua; class LuaCallbackObject : public osg::CallbackObject { public: LuaCallbackObject(const std::string& methodName, const LuaScriptEngine* lse, int ref):_lse(lse),_ref(ref) { setName(methodName); } virtual bool run(osg::Object* object, osg::Parameters& inputParameters, osg::Parameters& outputParameters) const { int topBeforeCall = lua_gettop(_lse->getLuaState()); lua_rawgeti(_lse->getLuaState(), LUA_REGISTRYINDEX, _ref); int numInputs = 1; _lse->pushParameter(object); for(osg::Parameters::iterator itr = inputParameters.begin(); itr != inputParameters.end(); ++itr) { _lse->pushParameter(itr->get()); ++numInputs; } if (lua_pcall(_lse->getLuaState(), numInputs, LUA_MULTRET,0)!=0) { OSG_NOTICE<<"Lua error : "<getLuaState(), -1)<getLuaState()); int numReturns = topAfterCall-topBeforeCall; for(int i=1; i<=numReturns; ++i) { outputParameters.insert(outputParameters.begin(), _lse->popParameterObject()); } return true; } int getRef() const { return _ref; } protected: osg::ref_ptr _lse; int _ref; }; static int getProperty(lua_State * _lua) { const LuaScriptEngine* lse = reinterpret_cast(lua_topointer(_lua, lua_upvalueindex(1))); int n = lua_gettop(_lua); /* number of arguments */ if (n==2 && lua_type(_lua, 1)==LUA_TTABLE) { if (lua_type(_lua, 2)==LUA_TSTRING) { std::string propertyName = lua_tostring(_lua, 2); osg::Object* object = lse->getObjectFromTable(1); return lse->pushPropertyToStack(object, propertyName); } } OSG_NOTICE<<"Warning: Lua getProperty() not matched"<(lua_topointer(_lua, lua_upvalueindex(1))); int n = lua_gettop(_lua); /* number of arguments */ if (n==3 && lua_type(_lua, 1)==LUA_TTABLE) { if (lua_type(_lua, 2)==LUA_TSTRING) { std::string propertyName = lua_tostring(_lua, 2); osg::Object* object = lse->getObjectFromTable(1); return lse->setPropertyFromStack(object, propertyName); } } OSG_NOTICE<<"Warning: Lua setProperty() not matched"<(lua_topointer(_lua, lua_upvalueindex(1))); int n = lua_gettop(_lua); /* number of arguments */ if (n==2 && lua_type(_lua, 1)==LUA_TTABLE) { if (lua_type(_lua, 2)==LUA_TSTRING) { std::string propertyName = lua_tostring(_lua, 2); osg::Object* object = lse->getObjectFromTable(1); std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName"); return lse->pushPropertyToStack(object, propertyName); } else if (lua_type(_lua, 2)==LUA_TNUMBER) { double index = lua_tonumber(_lua, 2); const osg::Object* object = lse->getObjectFromTable(1); std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName"); // check to see if Object "is a" vector osgDB::BaseSerializer::Type type; osgDB::BaseSerializer* bs = lse->getPropertyInterface().getSerializer(object, containerPropertyName, type); osgDB::VectorBaseSerializer* vs = dynamic_cast(bs); if (vs) { const void* dataPtr = vs->getElement(*object, index); if (dataPtr) { SerializerScratchPad valuesp(vs->getElementType(), dataPtr, vs->getElementSize()); return lse->pushDataToStack(&valuesp); } else { lua_pushnil(_lua); return 1; } } } } OSG_NOTICE<<"Warning: Lua getContainerProperty() not matched"<(lua_topointer(_lua, lua_upvalueindex(1))); int n = lua_gettop(_lua); /* number of arguments */ if (n==3 && lua_type(_lua, 1)==LUA_TTABLE) { if (lua_type(_lua, 2)==LUA_TSTRING) { std::string propertyName = lua_tostring(_lua, 2); osg::Object* object = lse->getObjectFromTable(1); std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName"); return lse->setPropertyFromStack(object, propertyName); } else if (lua_type(_lua, 2)==LUA_TNUMBER) { double index = lua_tonumber(_lua, 2); osg::Object* object = lse->getObjectFromTable(1); std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName"); // check to see if Object "is a" vector osgDB::BaseSerializer::Type type; osgDB::BaseSerializer* bs = lse->getPropertyInterface().getSerializer(object, containerPropertyName, type); osgDB::VectorBaseSerializer* vs = dynamic_cast(bs); if (vs) { SerializerScratchPad ssp; lse->getDataFromStack(&ssp, vs->getElementType(), 3); { vs->setElement(*object, index, ssp.data); } } return 0; } } OSG_NOTICE<<"Warning: Lua setContainerProperty() not matched"<(lua_topointer(_lua, lua_upvalueindex(1))); int n = lua_gettop(_lua); /* number of arguments */ if (n<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0; osg::Object* object = lse->getObjectFromTable(1); std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName"); // check to see if Object "is a" vector osgDB::BaseSerializer::Type type; osgDB::BaseSerializer* bs = lse->getPropertyInterface().getSerializer(object, containerPropertyName, type); osgDB::VectorBaseSerializer* vs = dynamic_cast(bs); if (vs) { lua_pushinteger(lse->getLuaState(), vs->size(*object)); return 1; } return 0; } static int callVectorClear(lua_State* _lua) { const LuaScriptEngine* lse = reinterpret_cast(lua_topointer(_lua, lua_upvalueindex(1))); int n = lua_gettop(_lua); /* number of arguments */ if (n<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0; osg::Object* object = lse->getObjectFromTable(1); std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName"); // check to see if Object "is a" vector osgDB::BaseSerializer::Type type; osgDB::BaseSerializer* bs = lse->getPropertyInterface().getSerializer(object, containerPropertyName, type); osgDB::VectorBaseSerializer* vs = dynamic_cast(bs); if (vs) { vs->clear(*object); return 0; } return 0; } static int callVectorResize(lua_State* _lua) { const LuaScriptEngine* lse = reinterpret_cast(lua_topointer(_lua, lua_upvalueindex(1))); int n = lua_gettop(_lua); /* number of arguments */ if (n<2 || lua_type(_lua, 1)!=LUA_TTABLE || lua_type(_lua, 2)!=LUA_TNUMBER) return 0; double numElements = lua_tonumber(lse->getLuaState(),2); osg::Object* object = lse->getObjectFromTable(1); std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName"); // check to see if Object "is a" vector osgDB::BaseSerializer::Type type; osgDB::BaseSerializer* bs = lse->getPropertyInterface().getSerializer(object, containerPropertyName, type); osgDB::VectorBaseSerializer* vs = dynamic_cast(bs); if (vs) { vs->resize(*object, static_cast(numElements)); } return 0; } static int callVectorReserve(lua_State* _lua) { const LuaScriptEngine* lse = reinterpret_cast(lua_topointer(_lua, lua_upvalueindex(1))); int n = lua_gettop(_lua); /* number of arguments */ if (n<2 || lua_type(_lua, 1)!=LUA_TTABLE || lua_type(_lua, 2)!=LUA_TNUMBER) return 0; double numElements = lua_tonumber(lse->getLuaState(),2); osg::Object* object = lse->getObjectFromTable(1); std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName"); // check to see if Object "is a" vector osgDB::BaseSerializer::Type type; osgDB::BaseSerializer* bs = lse->getPropertyInterface().getSerializer(object, containerPropertyName, type); osgDB::VectorBaseSerializer* vs = dynamic_cast(bs); if (vs) { vs->reserve(*object, static_cast(numElements)); } return 0; } static int callVectorAdd(lua_State* _lua) { const LuaScriptEngine* lse = reinterpret_cast(lua_topointer(_lua, lua_upvalueindex(1))); int n = lua_gettop(_lua); /* number of arguments */ if (n<2 || lua_type(_lua, 1)!=LUA_TTABLE) return 0; osg::Object* object = lse->getObjectFromTable(1); std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName"); // check to see if Object "is a" vector osgDB::BaseSerializer::Type type; osgDB::BaseSerializer* bs = lse->getPropertyInterface().getSerializer(object, containerPropertyName, type); osgDB::VectorBaseSerializer* vs = dynamic_cast(bs); if (vs) { SerializerScratchPad ssp; lse->getDataFromStack(&ssp, vs->getElementType(), 2); { vs->addElement(*object, ssp.data); } } return 0; } ////////////////////////////////////////////////////////////////////////////////////// // // Map container support // static int getMapProperty(lua_State * _lua) { const LuaScriptEngine* lse = reinterpret_cast(lua_topointer(_lua, lua_upvalueindex(1))); int n = lua_gettop(_lua); /* number of arguments */ if (n==2 && lua_type(_lua, 1)==LUA_TTABLE) { if (lua_type(_lua, 2)==LUA_TSTRING) { std::string propertyName = lua_tostring(_lua, 2); osg::Object* object = lse->getObjectFromTable(1); std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName"); return lse->pushPropertyToStack(object, propertyName); } else { const osg::Object* object = lse->getObjectFromTable(1); std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName"); // check to see if Object "is a" vector osgDB::BaseSerializer::Type type; osgDB::BaseSerializer* bs = lse->getPropertyInterface().getSerializer(object, containerPropertyName, type); osgDB::MapBaseSerializer* ms = dynamic_cast(bs); if (ms) { SerializerScratchPad keysp; lse->getDataFromStack(&keysp, ms->getKeyType(),2); if (keysp.dataType==ms->getKeyType()) { const void* dataPtr = ms->getElement(*object, keysp.data); if (dataPtr) { SerializerScratchPad valuesp(ms->getElementType(), dataPtr, ms->getElementSize()); return lse->pushDataToStack(&valuesp); } else { lua_pushnil(_lua); return 1; } return 0; } } } } OSG_NOTICE<<"Warning: Lua getMapProperty() not matched"<(lua_topointer(_lua, lua_upvalueindex(1))); int n = lua_gettop(_lua); /* number of arguments */ if (n==3 && lua_type(_lua, 1)==LUA_TTABLE) { if (lua_type(_lua, 2)==LUA_TSTRING) { std::string propertyName = lua_tostring(_lua, 2); osg::Object* object = lse->getObjectFromTable(1); std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName"); return lse->setPropertyFromStack(object, propertyName); } else { osg::Object* object = lse->getObjectFromTable(1); std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName"); // check to see if Object "is a" vector osgDB::BaseSerializer::Type type; osgDB::BaseSerializer* bs = lse->getPropertyInterface().getSerializer(object, containerPropertyName, type); osgDB::MapBaseSerializer* ms = dynamic_cast(bs); if (ms) { SerializerScratchPad keysp, valuesp; lse->getDataFromStack(&keysp, ms->getKeyType(),2); lse->getDataFromStack(&valuesp, ms->getElementType(),3); if (keysp.dataType==ms->getKeyType() && ms->getElementType()==valuesp.dataType) { ms->setElement(*object, keysp.data, valuesp.data); return 0; } else { OSG_NOTICE<<"Warning: Lua setMapProperty() : Failed to matched map element "<(lua_topointer(_lua, lua_upvalueindex(1))); int n = lua_gettop(_lua); /* number of arguments */ if (n<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0; osg::Object* object = lse->getObjectFromTable(1); std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName"); // check to see if Object "is a" vector osgDB::BaseSerializer::Type type; osgDB::BaseSerializer* bs = lse->getPropertyInterface().getSerializer(object, containerPropertyName, type); osgDB::MapBaseSerializer* ms = dynamic_cast(bs); if (ms) { ms->clear(*object); return 0; } return 0; } static int getMapSize(lua_State* _lua) { const LuaScriptEngine* lse = reinterpret_cast(lua_topointer(_lua, lua_upvalueindex(1))); int n = lua_gettop(_lua); /* number of arguments */ if (n<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0; osg::Object* object = lse->getObjectFromTable(1); std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName"); // check to see if Object "is a" vector osgDB::BaseSerializer::Type type; osgDB::BaseSerializer* bs = lse->getPropertyInterface().getSerializer(object, containerPropertyName, type); osgDB::MapBaseSerializer* ms = dynamic_cast(bs); if (ms) { lua_pushinteger(lse->getLuaState(), ms->size(*object)); return 1; } return 0; } static int createMapIterator(lua_State* _lua) { const LuaScriptEngine* lse = reinterpret_cast(lua_topointer(_lua, lua_upvalueindex(1))); int n = lua_gettop(_lua); /* number of arguments */ if (n<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0; osg::Object* object = lse->getObjectFromTable(1); std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName"); // check to see if Object "is a" vector osgDB::BaseSerializer::Type type; osgDB::BaseSerializer* bs = lse->getPropertyInterface().getSerializer(object, containerPropertyName, type); osgDB::MapBaseSerializer* ms = dynamic_cast(bs); if (ms) { lse->pushObject(ms->createIterator(*object)); return 1; } return 0; } static int createMapReverseIterator(lua_State* _lua) { const LuaScriptEngine* lse = reinterpret_cast(lua_topointer(_lua, lua_upvalueindex(1))); int n = lua_gettop(_lua); /* number of arguments */ if (n<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0; osg::Object* object = lse->getObjectFromTable(1); std::string containerPropertyName = lse->getStringFromTable(1,"containerPropertyName"); // check to see if Object "is a" vector osgDB::BaseSerializer::Type type; osgDB::BaseSerializer* bs = lse->getPropertyInterface().getSerializer(object, containerPropertyName, type); osgDB::MapBaseSerializer* ms = dynamic_cast(bs); if (ms) { lse->pushObject(ms->createReverseIterator(*object)); return 1; } return 0; } ////////////////////////////////////////////////////////////////////////////////////// // // MapIteratorObject support // static int callMapIteratorAdvance(lua_State* _lua) { const LuaScriptEngine* lse = reinterpret_cast(lua_topointer(_lua, lua_upvalueindex(1))); if (lua_gettop(_lua)<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0; osgDB::MapIteratorObject* mio = lse->getObjectFromTable(1); if (mio) { lua_pushboolean(lse->getLuaState(), mio->advance()); return 1; } return 0; } static int callMapIteratorValid(lua_State* _lua) { const LuaScriptEngine* lse = reinterpret_cast(lua_topointer(_lua, lua_upvalueindex(1))); if (lua_gettop(_lua)<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0; osgDB::MapIteratorObject* mio = lse->getObjectFromTable(1); if (mio) { lua_pushboolean(lse->getLuaState(), mio->valid()); return 1; } return 0; } static int getMapIteratorKey(lua_State* _lua) { const LuaScriptEngine* lse = reinterpret_cast(lua_topointer(_lua, lua_upvalueindex(1))); if (lua_gettop(_lua)<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0; osgDB::MapIteratorObject* mio = lse->getObjectFromTable(1); if (mio) { const void* dataPtr = mio->getKey(); if (dataPtr) { SerializerScratchPad valuesp(mio->getKeyType(), dataPtr, mio->getKeySize()); return lse->pushDataToStack(&valuesp); } else { lua_pushnil(_lua); return 1; } } return 0; } static int getMapIteratorElement(lua_State* _lua) { const LuaScriptEngine* lse = reinterpret_cast(lua_topointer(_lua, lua_upvalueindex(1))); if (lua_gettop(_lua)<1 || lua_type(_lua, 1)!=LUA_TTABLE) return 0; osgDB::MapIteratorObject* mio = lse->getObjectFromTable(1); if (mio) { const void* dataPtr = mio->getElement(); if (dataPtr) { SerializerScratchPad valuesp(mio->getElementType(), dataPtr, mio->getElementSize()); return lse->pushDataToStack(&valuesp); } else { lua_pushnil(_lua); return 1; } } OSG_NOTICE<<"getMapIteratorElement failed. "<(lua_topointer(_lua, lua_upvalueindex(1))); if (lua_gettop(_lua)<2 || lua_type(_lua, 1)!=LUA_TTABLE) return 0; osgDB::MapIteratorObject* mio = lse->getObjectFromTable(1); if (mio) { SerializerScratchPad valuesp; lse->getDataFromStack(&valuesp, mio->getElementType(), 2); if (mio->getElementType()==valuesp.dataType) { OSG_NOTICE<<"Assigning element "<setElement(valuesp.data); return 0; } else { OSG_NOTICE<<"Warning: Lua setMapIteratorElement() : Failed to matched map element type, valuesp.dataType="<(lua_topointer(_lua, lua_upvalueindex(1))); std::string methodName = lua_tostring(_lua, lua_upvalueindex(2)); int n = lua_gettop(_lua); /* number of arguments */ if (n>=1 && lua_type(_lua, 1)==LUA_TTABLE) { osg::Object* object = lse->getObjectFromTable(1); const std::string compoundClassName = lse->getObjectCompoundClassName(1); // object->getCompoundClassName(); // OSG_NOTICE<<"callClassMethod() on "<className()<<" method name "<popParameterObject()); } if (lse->getPropertyInterface().run(object, compoundClassName, methodName, inputParameters, outputParameters)) { for(osg::Parameters::iterator itr = outputParameters.begin(); itr != outputParameters.end(); ++itr) { // OSG_NOTICE<<" pushing return "<<(*itr)->className()<pushParameter(itr->get()); } return outputParameters.size(); } } else { OSG_NOTICE<<"Warning: lua method called without passing object, use object::method() convention."<(reinterpret_cast(lua_touserdata(_lua, 1))); object->unref(); } } return 0; } static int newObject(lua_State * _lua) { const LuaScriptEngine* lse = reinterpret_cast(lua_topointer(_lua, lua_upvalueindex(1))); int n = lua_gettop(_lua); /* number of arguments */ if (n==1) { if (lua_type(_lua, 1)==LUA_TSTRING) { std::string compoundName = lua_tostring(_lua, 1); lse->createAndPushObject(compoundName); return 1; } } return 0; } static int castObject(lua_State * _lua) { const LuaScriptEngine* lse = reinterpret_cast(lua_topointer(_lua, lua_upvalueindex(1))); int n = lua_gettop(_lua); /* number of arguments */ if (n==2) { if (lua_type(_lua, 1)==LUA_TSTRING && lua_type(_lua, 2)==LUA_TTABLE) { std::string new_compoundClassName = lua_tostring(_lua, 1); osg::Object* object = lse->getObjectFromTable(2); lse->pushAndCastObject(new_compoundClassName, object); return 1; } } return 0; } static int readObjectFile(lua_State * _lua) { const LuaScriptEngine* lse = reinterpret_cast(lua_topointer(_lua, lua_upvalueindex(1))); int n = lua_gettop(_lua); /* number of arguments */ if (n==1 && lua_type(_lua, 1)==LUA_TSTRING) { std::string filename = lua_tostring(_lua, 1); osg::ref_ptr object = osgDB::readObjectFile(filename); if (object.valid()) { lse->pushObject(object.get()); return 1; } } return 0; } static int readImageFile(lua_State * _lua) { const LuaScriptEngine* lse = reinterpret_cast(lua_topointer(_lua, lua_upvalueindex(1))); int n = lua_gettop(_lua); /* number of arguments */ if (n==1 && lua_type(_lua, 1)==LUA_TSTRING) { std::string filename = lua_tostring(_lua, 1); osg::ref_ptr image = osgDB::readImageFile(filename); if (image.valid()) { lse->pushObject(image.get()); return 1; } } return 0; } static int readNodeFile(lua_State * _lua) { const LuaScriptEngine* lse = reinterpret_cast(lua_topointer(_lua, lua_upvalueindex(1))); int n = lua_gettop(_lua); /* number of arguments */ if (n==1 && lua_type(_lua, 1)==LUA_TSTRING) { std::string filename = lua_tostring(_lua, 1); osg::ref_ptr node = osgDB::readNodeFile(filename); if (node.valid()) { lse->pushObject(node.get()); return 1; } } return 0; } LuaScriptEngine::LuaScriptEngine(): osg::ScriptEngine("lua"), _lua(0), _scriptCount(0) { initialize(); } LuaScriptEngine::LuaScriptEngine(const LuaScriptEngine& rhs, const osg::CopyOp&): osg::ScriptEngine("lua"), _lua(0), _scriptCount(0) { initialize(); } LuaScriptEngine::~LuaScriptEngine() { lua_close(_lua); } std::string LuaScriptEngine::createUniquieScriptName() { std::stringstream sstr; sstr<<"script_"<<_scriptCount; ++_scriptCount; return sstr.str(); } void LuaScriptEngine::initialize() { _lua = luaL_newstate(); luaL_openlibs(_lua); // provide global new method for creating osg::Object's. { lua_pushlightuserdata(_lua, this); lua_pushcclosure(_lua, newObject, 1); lua_setglobal(_lua, "new"); } // provide global new method for casting osg::Object's. { lua_pushlightuserdata(_lua, this); lua_pushcclosure(_lua, castObject, 1); lua_setglobal(_lua, "cast"); } // provide global new method for reading Objects { lua_pushlightuserdata(_lua, this); lua_pushcclosure(_lua, readObjectFile, 1); lua_setglobal(_lua, "readObjectFile"); } // provide global new method for reading Nodes { lua_pushlightuserdata(_lua, this); lua_pushcclosure(_lua, readNodeFile, 1); lua_setglobal(_lua, "readNodeFile"); } // provide global new method for read Images { lua_pushlightuserdata(_lua, this); lua_pushcclosure(_lua, readImageFile, 1); lua_setglobal(_lua, "readImageFile"); } // Set up the __newindex and __index methods for looking up implementations of Object properties { luaL_newmetatable(_lua, "LuaScriptEngine.Object"); lua_pushstring(_lua, "__index"); lua_pushlightuserdata(_lua, this); lua_pushcclosure(_lua, getProperty, 1); lua_settable(_lua, -3); lua_pushstring(_lua, "__newindex"); lua_pushlightuserdata(_lua, this); lua_pushcclosure(_lua, setProperty, 1); lua_settable(_lua, -3); lua_pop(_lua,1); } // Set up the __newindex and __index methods for looking up implementations of Object properties { luaL_newmetatable(_lua, "LuaScriptEngine.Container"); lua_pushstring(_lua, "__index"); lua_pushlightuserdata(_lua, this); lua_pushcclosure(_lua, getContainerProperty, 1); lua_settable(_lua, -3); lua_pushstring(_lua, "__newindex"); lua_pushlightuserdata(_lua, this); lua_pushcclosure(_lua, setContainerProperty, 1); lua_settable(_lua, -3); lua_pop(_lua,1); } // Set up the __newindex and __index methods for looking up implementations of Object properties { luaL_newmetatable(_lua, "LuaScriptEngine.Map"); lua_pushstring(_lua, "__index"); lua_pushlightuserdata(_lua, this); lua_pushcclosure(_lua, getMapProperty, 1); lua_settable(_lua, -3); lua_pushstring(_lua, "__newindex"); lua_pushlightuserdata(_lua, this); lua_pushcclosure(_lua, setMapProperty, 1); lua_settable(_lua, -3); lua_pop(_lua,1); } // Set up the __gc methods for looking up implementations of Object pointer to do the unref when the associated Lua object is destroyed. { luaL_newmetatable(_lua, "LuaScriptEngine.UnrefObject"); lua_pushstring(_lua, "__gc"); lua_pushlightuserdata(_lua, this); lua_pushcclosure(_lua, garabageCollectObject, 1); lua_settable(_lua, -3); lua_pop(_lua,1); } } bool LuaScriptEngine::loadScript(osg::Script* script) { if (_loadedScripts.count(script)!=0) return true; int loadResult = luaL_loadstring(_lua, script->getScript().c_str()); if (loadResult==0) { std::string scriptID = createUniquieScriptName(); lua_pushvalue(_lua, -1); lua_setglobal(_lua, scriptID.c_str()); _loadedScripts[script] = scriptID; return true; } else { OSG_NOTICE << "LuaScriptEngine::luaL_loadstring(Script*) error: " << lua_tostring(_lua, -1) << std::endl; return false; } } bool LuaScriptEngine::run(osg::Script* script, const std::string& entryPoint, osg::Parameters& inputParameters, osg::Parameters& outputParameters) { if (!script || !_lua) return false; if (_loadedScripts.count(script)==0) { if (!loadScript(script)) return false; if (!entryPoint.empty()) { if (lua_pcall(_lua, 0, 0, 0)!=0) { OSG_NOTICE<< "error initialize script "<< lua_tostring(_lua, -1)<second; lua_getglobal(_lua, scriptID.c_str()); } else { lua_getglobal(_lua, entryPoint.c_str()); /* function to be called */ } for(osg::Parameters::const_iterator itr = inputParameters.begin(); itr != inputParameters.end(); ++itr) { pushParameter(itr->get()); } if (lua_pcall(_lua, inputParameters.size(), LUA_MULTRET,0)!=0) { OSG_NOTICE<<"Lua error : "< obj = popParameterObject(); if (obj.valid()) outputParameters.push_back(obj); } return true; } class PushStackValueVisitor : public osg::ValueObject::GetValueVisitor { public: const LuaScriptEngine* _lse; lua_State* _lua; PushStackValueVisitor(const LuaScriptEngine* lse) : _lse(lse) { _lua = const_cast(lse)->getLuaState(); } virtual void apply(bool value) { lua_pushboolean(_lua, value ? 0 : 1); } virtual void apply(char value) { lua_pushnumber(_lua, value); } virtual void apply(unsigned char value) { lua_pushnumber(_lua, value); } virtual void apply(short value) { lua_pushnumber(_lua, value); } virtual void apply(unsigned short value) { lua_pushnumber(_lua, value); } virtual void apply(int value) { lua_pushnumber(_lua, value); } virtual void apply(unsigned int value) { lua_pushnumber(_lua, value); } virtual void apply(float value) { lua_pushnumber(_lua, value); } virtual void apply(double value) { lua_pushnumber(_lua, value); } virtual void apply(const std::string& value) { lua_pushlstring(_lua, &value[0], value.size()); } virtual void apply(const osg::Vec2f& value) { _lse->pushValue(value); } virtual void apply(const osg::Vec3f& value) { _lse->pushValue(value); } virtual void apply(const osg::Vec4f& value) { _lse->pushValue(value); } virtual void apply(const osg::Vec2d& value) { _lse->pushValue(value); } virtual void apply(const osg::Vec3d& value) { _lse->pushValue(value); } virtual void apply(const osg::Vec4d& value) { _lse->pushValue(value); } virtual void apply(const osg::Quat& value) { _lse->pushValue(value); } virtual void apply(const osg::Plane& value) { _lse->pushValue(value); } virtual void apply(const osg::Matrixf& value) { _lse->pushValue(value); } virtual void apply(const osg::Matrixd& value) { _lse->pushValue(value); } }; #if LUA_VERSION_NUM<=501 #define lua_rawlen lua_strlen #endif class GetStackValueVisitor : public osg::ValueObject::SetValueVisitor { public: const LuaScriptEngine* _lse; lua_State* _lua; int _index; int _numberToPop; GetStackValueVisitor(const LuaScriptEngine* lse, int index) : _lse(lse), _lua(0), _index(index), _numberToPop(0) { _lua = const_cast(lse )->getLuaState(); } virtual void apply(bool& value) { if (lua_isboolean(_lua, _index)) { value = (lua_toboolean(_lua, _index)!=0); _numberToPop = 1; } } virtual void apply(char& value) { if (lua_isnumber(_lua, _index)) { value = lua_tonumber(_lua, _index)!=0; _numberToPop = 1; } } virtual void apply(unsigned char& value) { if (lua_isnumber(_lua, _index)) { value = lua_tonumber(_lua, _index)!=0; _numberToPop = 1; } } virtual void apply(short& value) { if (lua_isnumber(_lua, _index)) { value = lua_tonumber(_lua, _index)!=0; _numberToPop = 1; } } virtual void apply(unsigned short& value) { if (lua_isnumber(_lua, _index)) { value = lua_tonumber(_lua, _index)!=0; _numberToPop = 1; } } virtual void apply(int& value) { if (lua_isnumber(_lua, _index)) { value = lua_tonumber(_lua, _index)!=0; _numberToPop = 1; } } virtual void apply(unsigned int& value) { if (lua_isnumber(_lua, _index)) { value = lua_tonumber(_lua, _index)!=0; _numberToPop = 1; } } virtual void apply(float& value) { if (lua_isnumber(_lua, _index)) { value = lua_tonumber(_lua, _index)!=0; _numberToPop = 1; } } virtual void apply(double& value) { if (lua_isnumber(_lua, _index)) { value = lua_tonumber(_lua, _index)!=0; _numberToPop = 1; } } virtual void apply(std::string& value) { if (lua_isstring(_lua, _index)) { value = std::string(lua_tostring(_lua, _index), lua_rawlen(_lua, _index)); _numberToPop = 1; } } virtual void apply(osg::Vec2f& value) { _lse->getValue(_index, value); _numberToPop = 2;} virtual void apply(osg::Vec3f& value) { _lse->getValue(_index, value); _numberToPop = 2; } virtual void apply(osg::Vec4f& value) { _lse->getValue(_index, value); _numberToPop = 4; } virtual void apply(osg::Vec2d& value) { _lse->getValue(_index, value); _numberToPop = 2; } virtual void apply(osg::Vec3d& value) { _lse->getValue(_index, value); _numberToPop = 3; } virtual void apply(osg::Vec4d& value) { _lse->getValue(_index, value); _numberToPop = 4; } virtual void apply(osg::Quat& value) { _lse->getValue(_index, value); _numberToPop = 4; } virtual void apply(osg::Plane& value) { _lse->getValue(_index, value); _numberToPop = 4; } virtual void apply(osg::Matrixf& value) { _lse->getValue(_index, value); } virtual void apply(osg::Matrixd& value) { _lse->getValue(_index, value); } virtual void apply(osg::BoundingBoxf& value) { _lse->getValue(_index, value); } virtual void apply(osg::BoundingBoxd& value) { _lse->getValue(_index, value); } virtual void apply(osg::BoundingSpheref& value) { _lse->getValue(_index, value); } virtual void apply(osg::BoundingSphered& value) { _lse->getValue(_index, value); } }; int LuaScriptEngine::pushPropertyToStack(osg::Object* object, const std::string& propertyName) const { osgDB::BaseSerializer::Type type; if (!_pi.getPropertyType(object, propertyName, type)) { if (_pi.hasMethod(object, propertyName)) { lua_pushlightuserdata(_lua, const_cast(this)); lua_pushstring(_lua, propertyName.c_str()); lua_pushcclosure(_lua, callClassMethod, 2); return 1; } osg::Object* uo = osg::getUserObject(object, propertyName); LuaCallbackObject* lco = dynamic_cast(uo); if (lco) { lua_rawgeti(_lua, LUA_REGISTRYINDEX, lco->getRef()); return 1; } else if (uo) { pushObject(uo); return 1; } OSG_INFO<<"LuaScriptEngine::pushPropertyToStack("<getIntLookup() : 0; if (lookup) { std::string enumString = lookup->getString(value); lua_pushstring(_lua, enumString.c_str()); } else { lua_pushinteger(_lua, value); } return 1; } break; } case(osgDB::BaseSerializer::RW_SHORT): { short value; if (_pi.getProperty(object, propertyName, value)) { lua_pushinteger(_lua, value); return 1; } break; } case(osgDB::BaseSerializer::RW_USHORT): { unsigned short value; if (_pi.getProperty(object, propertyName, value)) { lua_pushinteger(_lua, value); return 1; } break; } case(osgDB::BaseSerializer::RW_INT): { int value; if (_pi.getProperty(object, propertyName, value)) { lua_pushinteger(_lua, value); return 1; } break; } case(osgDB::BaseSerializer::RW_UINT): { unsigned int value; if (_pi.getProperty(object, propertyName, value)) { lua_pushinteger(_lua, value); return 1; } break; } case(osgDB::BaseSerializer::RW_FLOAT): { float value; if (_pi.getProperty(object, propertyName, value)) { lua_pushnumber(_lua, value); return 1; } break; } case(osgDB::BaseSerializer::RW_DOUBLE): { double value; if (_pi.getProperty(object, propertyName, value)) { lua_pushnumber(_lua, value); return 1; } break; } case(osgDB::BaseSerializer::RW_VEC2F): { osg::Vec2f value; if (_pi.getProperty(object, propertyName, value)) { pushValue(value); return 1; } break; } case(osgDB::BaseSerializer::RW_VEC3F): { osg::Vec3f value; if (_pi.getProperty(object, propertyName, value)) { pushValue(value); return 1; } break; } case(osgDB::BaseSerializer::RW_VEC4F): { osg::Vec4f value; if (_pi.getProperty(object, propertyName, value)) { pushValue(value); return 1; } break; } case(osgDB::BaseSerializer::RW_VEC2D): { osg::Vec2d value; if (_pi.getProperty(object, propertyName, value)) { pushValue(value); return 1; } break; } case(osgDB::BaseSerializer::RW_VEC3D): { osg::Vec3d value; if (_pi.getProperty(object, propertyName, value)) { pushValue(value); return 1; } break; } case(osgDB::BaseSerializer::RW_VEC4D): { osg::Vec4d value; if (_pi.getProperty(object, propertyName, value)) { pushValue(value); return 1; } break; } #ifdef OSG_USE_FLOAT_MATRIX case(osgDB::BaseSerializer::RW_MATRIX): #endif case(osgDB::BaseSerializer::RW_MATRIXF): { osg::Matrixf value; if (_pi.getProperty(object, propertyName, value)) { pushValue(value); return 1; } break; } #ifndef OSG_USE_FLOAT_MATRIX case(osgDB::BaseSerializer::RW_MATRIX): #endif case(osgDB::BaseSerializer::RW_MATRIXD): { osg::Matrixd value; if (_pi.getProperty(object, propertyName, value)) { pushValue(value); return 1; } break; } case(osgDB::BaseSerializer::RW_BOUNDINGBOXF): { osg::BoundingBoxf value; if (_pi.getProperty(object, propertyName, value)) { pushValue(value); return 1; } break; } case(osgDB::BaseSerializer::RW_BOUNDINGBOXD): { osg::BoundingBoxd value; if (_pi.getProperty(object, propertyName, value)) { pushValue(value); return 1; } break; } case(osgDB::BaseSerializer::RW_BOUNDINGSPHEREF): { osg::BoundingSpheref value; if (_pi.getProperty(object, propertyName, value)) { pushValue(value); return 1; } break; } case(osgDB::BaseSerializer::RW_BOUNDINGSPHERED): { osg::BoundingSphered value; if (_pi.getProperty(object, propertyName, value)) { pushValue(value); return 1; } break; } case(osgDB::BaseSerializer::RW_LIST): { OSG_NOTICE<<"Need to implement RW_LIST support"<getObjectWrapperManager(); { const osgDB::IntLookup& lookup = ow->getLookupMap()["GL"]; const osgDB::IntLookup::ValueToString& vts = lookup.getValueToString(); osgDB::IntLookup::ValueToString::const_iterator itr = vts.find(value); if (itr!=vts.end()) return itr->second; } { const osgDB::IntLookup& lookup = ow->getLookupMap()["PrimitiveType"]; const osgDB::IntLookup::ValueToString& vts = lookup.getValueToString(); osgDB::IntLookup::ValueToString::const_iterator itr = vts.find(value); if (itr!=vts.end()) return itr->second; } OSG_NOTICE<<"Warning: LuaScriptEngine did not find valid GL enum value for GLenum value: "<getObjectWrapperManager(); { const osgDB::IntLookup& lookup = ow->getLookupMap()["GL"]; const osgDB::IntLookup::StringToValue& stv = lookup.getStringToValue(); osgDB::IntLookup::StringToValue::const_iterator itr = stv.find(str); if (itr!=stv.end()) return itr->second; } { const osgDB::IntLookup& lookup = ow->getLookupMap()["PrimitiveType"]; const osgDB::IntLookup::StringToValue& stv = lookup.getStringToValue(); osgDB::IntLookup::StringToValue::const_iterator itr = stv.find(str); if (itr!=stv.end()) return itr->second; } OSG_NOTICE<<"Warning: LuaScriptEngine did not find valid GL enum value for string value: "<dataType) { case(osgDB::BaseSerializer::RW_BOOL): { bool value; if (ssp->get(value)) { lua_pushboolean(_lua, value ? 1 : 0); return 1; } break; } case(osgDB::BaseSerializer::RW_STRING): { std::string value; if (ssp->get(value)) { lua_pushstring(_lua, value.c_str()); return 1; } break; } case(osgDB::BaseSerializer::RW_GLENUM): { GLenum value; if (ssp->get(value)) { std::string enumString = lookUpGLenumString(value); lua_pushstring(_lua, enumString.c_str()); return 1; } break; } case(osgDB::BaseSerializer::RW_ENUM): { int value; if (ssp->get(value)) { lua_pushinteger(_lua, value); return 1; } break; } case(osgDB::BaseSerializer::RW_INT): { int value; if (ssp->get(value)) { lua_pushinteger(_lua, value); return 1; } break; } case(osgDB::BaseSerializer::RW_UINT): { unsigned int value; if (ssp->get(value)) { lua_pushinteger(_lua, value); return 1; } break; } case(osgDB::BaseSerializer::RW_SHORT): { short value; if (ssp->get(value)) { lua_pushinteger(_lua, value); return 1; } break; } case(osgDB::BaseSerializer::RW_USHORT): { unsigned short value; if (ssp->get(value)) { lua_pushinteger(_lua, value); return 1; } break; } case(osgDB::BaseSerializer::RW_FLOAT): { float value; if (ssp->get(value)) { lua_pushnumber(_lua, value); return 1; } break; } case(osgDB::BaseSerializer::RW_DOUBLE): { double value; if (ssp->get(value)) { lua_pushnumber(_lua, value); return 1; } break; } case(osgDB::BaseSerializer::RW_VEC2F): { osg::Vec2f value; if (ssp->get(value)) { pushValue(value); return 1; } break; } case(osgDB::BaseSerializer::RW_VEC3F): { osg::Vec3f value; if (ssp->get(value)) { pushValue(value); return 1; } break; } case(osgDB::BaseSerializer::RW_VEC4F): { osg::Vec4f value; if (ssp->get(value)) { pushValue(value); return 1; } break; } case(osgDB::BaseSerializer::RW_VEC2D): { osg::Vec2d value; if (ssp->get(value)) { pushValue(value); return 1; } break; } case(osgDB::BaseSerializer::RW_VEC3D): { osg::Vec3d value; if (ssp->get(value)) { pushValue(value); return 1; } break; } case(osgDB::BaseSerializer::RW_VEC4D): { osg::Vec4d value; if (ssp->get(value)) { pushValue(value); return 1; } break; } #ifdef OSG_USE_FLOAT_MATRIX case(osgDB::BaseSerializer::RW_MATRIX): #endif case(osgDB::BaseSerializer::RW_MATRIXF): { osg::Matrixf value; if (ssp->get(value)) { pushValue(value); return 1; } break; } #ifndef OSG_USE_FLOAT_MATRIX case(osgDB::BaseSerializer::RW_MATRIX): #endif case(osgDB::BaseSerializer::RW_MATRIXD): { osg::Matrixd value; if (ssp->get(value)) { pushValue(value); return 1; } break; } case(osgDB::BaseSerializer::RW_BOUNDINGBOXF): { osg::BoundingBoxf value; if (ssp->get(value)) { pushValue(value); return 1; } break; } case(osgDB::BaseSerializer::RW_BOUNDINGBOXD): { osg::BoundingBoxd value; if (ssp->get(value)) { pushValue(value); return 1; } break; } case(osgDB::BaseSerializer::RW_BOUNDINGSPHEREF): { osg::BoundingSpheref value; if (ssp->get(value)) { pushValue(value); return 1; } break; } case(osgDB::BaseSerializer::RW_BOUNDINGSPHERED): { osg::BoundingSphered value; if (ssp->get(value)) { pushValue(value); return 1; } break; } case(osgDB::BaseSerializer::RW_IMAGE): case(osgDB::BaseSerializer::RW_OBJECT): { osg::Object* value = 0; if (ssp->get(value)) { pushObject(value); return 1; } break; } case(osgDB::BaseSerializer::RW_LIST): { break; } case(osgDB::BaseSerializer::RW_VECTOR): { break; } default: break; } OSG_NOTICE<<"LuaScriptEngine::pushDataToStack() property of type = "<<_pi.getTypeName(ssp->dataType)<<" error, not supported."<set(static_cast(lua_toboolean(_lua, pos))); return 0; } else if (lua_isnumber(_lua, pos)) { ssp->set(static_cast(lua_tonumber(_lua, pos)!=0)); return 0; } break; } case(osgDB::BaseSerializer::RW_STRING): { if (lua_isstring(_lua, pos)) { ssp->set(std::string(lua_tostring(_lua, pos))); return 0; } break; } case(osgDB::BaseSerializer::RW_GLENUM): { if (lua_isnumber(_lua, pos)) { ssp->set(static_cast(lua_tonumber(_lua, pos))); return 0; } else if (lua_isstring(_lua, pos)) { const char* enumString = lua_tostring(_lua, pos); GLenum value = lookUpGLenumValue(enumString); //getValue("GL",enumString); ssp->set(value); return 0; } OSG_NOTICE<<"LuaScriptEngine::getDataFromStack() osgDB::BaseSerializer::RW_GLENUM Failed"<set(static_cast(lua_tonumber(_lua, pos))); return 0; } else if (lua_isstring(_lua, pos)) { OSG_NOTICE<<"LuaScriptEngine::getDataFromStack() osgDB::BaseSerializer::RW_ENUM Failed to convert string"<set(static_cast(lua_tonumber(_lua, pos))); return 0; } break; } case(osgDB::BaseSerializer::RW_USHORT): { if (lua_isnumber(_lua, pos)) { ssp->set(static_cast(lua_tonumber(_lua, pos))); return 0; } break; } case(osgDB::BaseSerializer::RW_INT): { if (lua_isnumber(_lua, pos)) { ssp->set(static_cast(lua_tonumber(_lua, pos))); return 0; } break; } case(osgDB::BaseSerializer::RW_UINT): { if (lua_isnumber(_lua, pos)) { ssp->set(static_cast(lua_tonumber(_lua, pos))); return 0; } break; } case(osgDB::BaseSerializer::RW_FLOAT): { if (lua_isnumber(_lua, pos)) { ssp->set(static_cast(lua_tonumber(_lua, pos))); return 0; } break; } case(osgDB::BaseSerializer::RW_DOUBLE): { if (lua_isnumber(_lua, pos)) { ssp->set(static_cast(lua_tonumber(_lua, pos))); return 0; } break; } case(osgDB::BaseSerializer::RW_VEC2F): { osg::Vec2f value; if (getValue(pos, value)) { ssp->set(value); return 0; } break; } case(osgDB::BaseSerializer::RW_VEC3F): { osg::Vec3f value; if (getValue(pos, value)) { ssp->set(value); return 0; } break; } case(osgDB::BaseSerializer::RW_VEC4F): { osg::Vec4f value; if (getValue(pos, value)) { ssp->set(value); return 0; } break; } case(osgDB::BaseSerializer::RW_VEC2D): { osg::Vec2d value; if (getValue(pos, value)) { ssp->set(value); return 0; } break; } case(osgDB::BaseSerializer::RW_VEC3D): { osg::Vec3d value; if (getValue(pos, value)) { ssp->set(value); return 0; } break; } case(osgDB::BaseSerializer::RW_VEC4D): { osg::Vec4d value; if (getValue(pos, value)) { ssp->set(value); return 0; } break; } case(osgDB::BaseSerializer::RW_QUAT): { osg::Quat value; if (getValue(pos, value)) { ssp->set(value); return 0; } break; } case(osgDB::BaseSerializer::RW_PLANE): { osg::Plane value; if (getValue(pos, value)) { ssp->set(value); return 0; } break; } #ifdef OSG_USE_FLOAT_MATRIX case(osgDB::BaseSerializer::RW_MATRIX): #endif case(osgDB::BaseSerializer::RW_MATRIXF): { osg::Matrixd value; if (getValue(pos, value)) { ssp->set(value); return 0; } break; } #ifndef OSG_USE_FLOAT_MATRIX case(osgDB::BaseSerializer::RW_MATRIX): #endif case(osgDB::BaseSerializer::RW_MATRIXD): { osg::Matrixd value; if (getValue(pos, value)) { ssp->set(value); return 0; } break; } case(osgDB::BaseSerializer::RW_BOUNDINGBOXF): { osg::BoundingBoxf value; if (getValue(pos, value)) { ssp->set(value); return 0; } break; } case(osgDB::BaseSerializer::RW_BOUNDINGBOXD): { osg::BoundingBoxd value; if (getValue(pos, value)) { ssp->set(value); return 0; } break; } case(osgDB::BaseSerializer::RW_BOUNDINGSPHEREF): { osg::BoundingSpheref value; if (getValue(pos, value)) { ssp->set(value); return 0; } break; } case(osgDB::BaseSerializer::RW_BOUNDINGSPHERED): { osg::BoundingSphered value; if (getValue(pos, value)) { ssp->set(value); return 0; } break; } case(osgDB::BaseSerializer::RW_LIST): { OSG_NOTICE<<"Need to implement RW_LIST support"<(reinterpret_cast(lua_touserdata(_lua,-1))); lua_pop(_lua, 1); if (value) { ssp->set(value); return 0; } else { OSG_NOTICE<<"Error: lua type '"<set(value); return 0; } else { OSG_NOTICE<<"Error: lua type '"< lco = new LuaCallbackObject(propertyName, this, ref); object->getOrCreateUserDataContainer()->addUserObject(lco.get()); return 0; } type = LuaScriptEngine::getType(-1); } switch(type) { case(osgDB::BaseSerializer::RW_BOOL): { if (lua_isboolean(_lua, -1)) { _pi.setProperty(object, propertyName, static_cast(lua_toboolean(_lua, -1))); return 0; } else if (lua_isnumber(_lua, -1)) { _pi.setProperty(object, propertyName, static_cast(lua_tonumber(_lua, -1)!=0)); return 0; } break; } case(osgDB::BaseSerializer::RW_STRING): { if (lua_isstring(_lua, -1)) { _pi.setProperty(object, propertyName, std::string(lua_tostring(_lua, -1))); return 0; } break; } case(osgDB::BaseSerializer::RW_GLENUM): { if (lua_isnumber(_lua, -1)) { _pi.setProperty(object, propertyName, static_cast(lua_tonumber(_lua, -1))); return 0; } else if (lua_isstring(_lua, -1)) { const char* enumString = lua_tostring(_lua, -1); GLenum value = lookUpGLenumValue(enumString); //getValue("GL",enumString); _pi.setProperty(object, propertyName, value); return 0; } OSG_NOTICE<<"LuaScriptEngine::setPropertyFromStack("<(lua_tonumber(_lua, -1))); return 0; } else if (lua_isstring(_lua, -1)) { const char* enumString = lua_tostring(_lua, -1); osgDB::BaseSerializer* serializer = _pi.getSerializer(object, propertyName, type); osgDB::IntLookup* lookup = serializer ? serializer->getIntLookup() : 0; if (lookup) { int value = lookup->getValue(enumString); _pi.setProperty(object, propertyName, value); } return 0; } break; } case(osgDB::BaseSerializer::RW_SHORT): { if (lua_isnumber(_lua, -1)) { _pi.setProperty(object, propertyName, static_cast(lua_tonumber(_lua, -1))); return 0; } break; } case(osgDB::BaseSerializer::RW_USHORT): { if (lua_isnumber(_lua, -1)) { _pi.setProperty(object, propertyName, static_cast(lua_tonumber(_lua, -1))); return 0; } break; } case(osgDB::BaseSerializer::RW_INT): { if (lua_isnumber(_lua, -1)) { _pi.setProperty(object, propertyName, static_cast(lua_tonumber(_lua, -1))); return 0; } break; } case(osgDB::BaseSerializer::RW_UINT): { if (lua_isnumber(_lua, -1)) { _pi.setProperty(object, propertyName, static_cast(lua_tonumber(_lua, -1))); return 0; } break; } case(osgDB::BaseSerializer::RW_FLOAT): { if (lua_isnumber(_lua, -1)) { _pi.setProperty(object, propertyName, static_cast(lua_tonumber(_lua, -1))); return 0; } break; } case(osgDB::BaseSerializer::RW_DOUBLE): { if (lua_isnumber(_lua, -1)) { _pi.setProperty(object, propertyName, static_cast(lua_tonumber(_lua, -1))); return 0; } break; } case(osgDB::BaseSerializer::RW_VEC2F): { osg::Vec2f value; if (getValue(-1, value)) { _pi.setProperty(object, propertyName, value); return 0; } break; } case(osgDB::BaseSerializer::RW_VEC3F): { osg::Vec3f value; if (getValue(-1, value)) { _pi.setProperty(object, propertyName, value); return 0; } break; } case(osgDB::BaseSerializer::RW_VEC4F): { osg::Vec4f value; if (getValue(-1, value)) { _pi.setProperty(object, propertyName, value); return 0; } break; } case(osgDB::BaseSerializer::RW_VEC2D): { osg::Vec2d value; if (getValue(-1, value)) { _pi.setProperty(object, propertyName, value); return 0; } break; } case(osgDB::BaseSerializer::RW_VEC3D): { osg::Vec3d value; if (getValue(-1, value)) { _pi.setProperty(object, propertyName, value); return 0; } break; } case(osgDB::BaseSerializer::RW_VEC4D): { osg::Vec4d value; if (getValue(-1, value)) { _pi.setProperty(object, propertyName, value); return 0; } break; } case(osgDB::BaseSerializer::RW_QUAT): { osg::Quat value; if (getValue(-1, value)) { _pi.setProperty(object, propertyName, value); return 0; } break; } case(osgDB::BaseSerializer::RW_PLANE): { osg::Plane value; if (getValue(-1, value)) { _pi.setProperty(object, propertyName, value); return 0; } break; } #ifdef OSG_USE_FLOAT_MATRIX case(osgDB::BaseSerializer::RW_MATRIX): #endif case(osgDB::BaseSerializer::RW_MATRIXF): { osg::Matrixd value; if (getValue(-1, value)) { _pi.setProperty(object, propertyName, value); return 0; } break; } #ifndef OSG_USE_FLOAT_MATRIX case(osgDB::BaseSerializer::RW_MATRIX): #endif case(osgDB::BaseSerializer::RW_MATRIXD): { osg::Matrixd value; if (getValue(-1, value)) { _pi.setProperty(object, propertyName, value); return 0; } break; } case(osgDB::BaseSerializer::RW_BOUNDINGBOXF): { osg::BoundingBoxf value; if (getValue(-1, value)) { _pi.setProperty(object, propertyName, value); return 0; } break; } case(osgDB::BaseSerializer::RW_BOUNDINGBOXD): { osg::BoundingBoxd value; if (getValue(-1, value)) { _pi.setProperty(object, propertyName, value); return 0; } break; } case(osgDB::BaseSerializer::RW_BOUNDINGSPHEREF): { osg::BoundingSpheref value; if (getValue(-1, value)) { _pi.setProperty(object, propertyName, value); return 0; } break; } case(osgDB::BaseSerializer::RW_BOUNDINGSPHERED): { osg::BoundingSphered value; if (getValue(-1, value)) { _pi.setProperty(object, propertyName, value); return 0; } break; } case(osgDB::BaseSerializer::RW_LIST): { OSG_NOTICE<<"Need to implement RW_LIST support"<(reinterpret_cast(lua_touserdata(_lua,-1))); lua_pop(_lua, 1); if (value) { _pi.setProperty(object, propertyName, value); return 0; } else { OSG_NOTICE<<"Error: lua type '"<className()<<"::"<className()<<"::"<className()<<"::"<(object); if (vo) { PushStackValueVisitor pvv(this); vo->get(pvv); } else { pushObject( object); } return false; } bool LuaScriptEngine::popParameter(osg::Object* object) const { osg::ValueObject* vo = dynamic_cast(object); if (vo) { GetStackValueVisitor pvv(this, -1); vo->set(pvv); lua_pop(_lua, pvv._numberToPop); } else { lua_pop(_lua, 1); } return false; } osg::Object* LuaScriptEngine::popParameterObject() const { osg::ref_ptr object = 0; osgDB::BaseSerializer::Type type = getType(-1); switch(type) { case(osgDB::BaseSerializer::RW_BOOL): { if (lua_isboolean(_lua, -1)) object = new osg::BoolValueObject("", lua_toboolean(_lua, -1)!=0); break; } case(osgDB::BaseSerializer::RW_STRING): { if (lua_isstring(_lua, -1)) object = new osg::StringValueObject("", lua_tostring(_lua, -1)); break; } case(osgDB::BaseSerializer::RW_GLENUM): case(osgDB::BaseSerializer::RW_ENUM): if (lua_isstring(_lua, -1)) { object = new osg::StringValueObject("", lua_tostring(_lua, -1)); } else if (lua_isnumber(_lua, -1)) { object = new osg::IntValueObject("", static_cast(lua_tonumber(_lua, -1))); } break; case(osgDB::BaseSerializer::RW_INT): { if (lua_isnumber(_lua, -1)) object = new osg::IntValueObject("", static_cast(lua_tonumber(_lua, -1))); break; } case(osgDB::BaseSerializer::RW_UINT): { if (lua_isnumber(_lua, -1)) object = new osg::UIntValueObject("", static_cast(lua_tonumber(_lua, -1))); break; } case(osgDB::BaseSerializer::RW_FLOAT): { if (lua_isnumber(_lua, -1)) object = new osg::FloatValueObject("", static_cast(lua_tonumber(_lua, -1))); break; } case(osgDB::BaseSerializer::RW_DOUBLE): { if (lua_isnumber(_lua, -1)) object = new osg::DoubleValueObject("", static_cast(lua_tonumber(_lua, -1))); break; } case(osgDB::BaseSerializer::RW_VEC2F): { osg::Vec2f value; if (getValue(-1, value)) object = new osg::Vec2fValueObject("", value); break; } case(osgDB::BaseSerializer::RW_VEC3F): { osg::Vec3f value; if (getValue(-1, value)) object = new osg::Vec3fValueObject("", value); break; } case(osgDB::BaseSerializer::RW_VEC4F): { osg::Vec4f value; if (getValue(-1, value)) object = new osg::Vec4fValueObject("", value); break; } #ifdef OSG_USE_FLOAT_MATRIX case(osgDB::BaseSerializer::RW_MATRIX): #endif case(osgDB::BaseSerializer::RW_MATRIXF): { osg::Matrixf value; if (getValue(-1, value)) object = new osg::MatrixfValueObject("", value); break; } case(osgDB::BaseSerializer::RW_VEC2D): { osg::Vec2d value; if (getValue(-1, value)) object = new osg::Vec2dValueObject("", value); break; } case(osgDB::BaseSerializer::RW_VEC3D): { osg::Vec3d value; if (getValue(-1, value)) object = new osg::Vec3dValueObject("", value); break; } case(osgDB::BaseSerializer::RW_VEC4D): { osg::Vec4d value; if (getValue(-1, value)) object = new osg::Vec4dValueObject("", value); break; } case(osgDB::BaseSerializer::RW_QUAT): { osg::Quat value; if (getValue(-1, value)) object = new osg::QuatValueObject("", value); break; } case(osgDB::BaseSerializer::RW_PLANE): { osg::Plane value; if (getValue(-1, value)) object = new osg::PlaneValueObject("", value); break; } #ifndef OSG_USE_FLOAT_MATRIX case(osgDB::BaseSerializer::RW_MATRIX): #endif case(osgDB::BaseSerializer::RW_MATRIXD): { osg::Matrixd value; if (getValue(-1, value)) object = new osg::MatrixdValueObject("", value); break; } case(osgDB::BaseSerializer::RW_BOUNDINGBOXF): { osg::BoundingBoxf value; if (getValue(-1, value)) object = new osg::BoundingBoxfValueObject("", value); break; } case(osgDB::BaseSerializer::RW_BOUNDINGBOXD): { osg::BoundingBoxd value; if (getValue(-1, value)) object = new osg::BoundingBoxdValueObject("", value); break; } case(osgDB::BaseSerializer::RW_BOUNDINGSPHEREF): { osg::BoundingSpheref value; if (getValue(-1, value)) object = new osg::BoundingSpherefValueObject("", value); break; } case(osgDB::BaseSerializer::RW_BOUNDINGSPHERED): { osg::BoundingSphered value; if (getValue(-1, value)) object = new osg::BoundingSpheredValueObject("", value); break; } case(osgDB::BaseSerializer::RW_LIST): { OSG_NOTICE<<"Need to implement RW_LIST support"<(reinterpret_cast(lua_touserdata(_lua,-1))); } lua_pop(_lua, 1); } default: break; } lua_pop(_lua, 1); return object.release(); #if 0 osg::ValueObject* vo = dynamic_cast(object); if (vo) { GetStackValueVisitor pvv(this, -1); vo->set(pvv); lua_pop(_lua, pvv._numberToPop); } else { lua_pop(_lua, 1); } #endif return object.release(); } void LuaScriptEngine::pushContainer(osg::Object* object, const std::string& propertyName) const { if (object) { lua_newtable(_lua); // set up objbect_ptr to handle ref/unref of the object { lua_pushstring(_lua, "object_ptr"); // create user data for pointer void* userdata = lua_newuserdata( _lua, sizeof(osg::Object*)); (*reinterpret_cast(userdata)) = object; luaL_getmetatable( _lua, "LuaScriptEngine.UnrefObject"); lua_setmetatable( _lua, -2 ); lua_settable(_lua, -3); // increment the reference count as the lua now will unreference it once it's finished with the userdata for the pointer object->ref(); } lua_pushstring(_lua, "containerPropertyName"); lua_pushstring(_lua, propertyName.c_str()); lua_settable(_lua, -3); osgDB::BaseSerializer::Type type; osgDB::BaseSerializer* bs = _pi.getSerializer(object, propertyName, type); osgDB::VectorBaseSerializer* vs = dynamic_cast(bs); osgDB::MapBaseSerializer* ms = dynamic_cast(bs); if (vs) { assignClosure("size", getContainerSize); assignClosure("clear", callVectorClear); assignClosure("resize", callVectorResize); assignClosure("reserve", callVectorReserve); assignClosure("add", callVectorAdd); luaL_getmetatable(_lua, "LuaScriptEngine.Container"); lua_setmetatable(_lua, -2); } else if (ms) { assignClosure("clear", callMapClear); assignClosure("size", getMapSize); assignClosure("createIterator", createMapIterator); assignClosure("createReverseIterator", createMapReverseIterator); luaL_getmetatable(_lua, "LuaScriptEngine.Map"); lua_setmetatable(_lua, -2); } else { OSG_NOTICE<<"Container type not suppported."< object = _pi.createObject(compoundName); if (!object) OSG_NOTICE<<"Failed to create object "<(userdata)) = object; luaL_getmetatable( _lua, "LuaScriptEngine.UnrefObject"); lua_setmetatable( _lua, -2 ); lua_settable(_lua, -3); // increment the reference count as the lua now will unreference it once it's finished with the userdata for the pointer object->ref(); } lua_pushstring(_lua, "libraryName"); lua_pushstring(_lua, object->libraryName()); lua_settable(_lua, -3); lua_pushstring(_lua, "className"); lua_pushstring(_lua, object->className()); lua_settable(_lua, -3); lua_pushstring(_lua, "compoundClassName"); lua_pushstring(_lua, object->getCompoundClassName().c_str()); lua_settable(_lua, -3); // check to see if Object "is a" vector osgDB::BaseSerializer::Type type; osgDB::BaseSerializer* vs = _pi.getSerializer(object, "vector", type); if (vs) { OSG_NOTICE<<"pushObject("<className()<<" Have vector"<(object)!=0) { assignClosure("advance", callMapIteratorAdvance); assignClosure("valid", callMapIteratorValid); assignClosure("getKey", getMapIteratorKey); assignClosure("getElement", getMapIteratorElement); assignClosure("setElement", setMapIteratorElement); } else { luaL_getmetatable(_lua, "LuaScriptEngine.Object"); lua_setmetatable(_lua, -2); } } else { lua_pushnil(_lua); } } void LuaScriptEngine::pushAndCastObject(const std::string& compoundClassName, osg::Object* object) const { if (object && _pi.isObjectOfType(object, compoundClassName)) { lua_newtable(_lua); // set up objbect_ptr to handle ref/unref of the object { lua_pushstring(_lua, "object_ptr"); // create user data for pointer void* userdata = lua_newuserdata( _lua, sizeof(osg::Object*)); (*reinterpret_cast(userdata)) = object; luaL_getmetatable( _lua, "LuaScriptEngine.UnrefObject"); lua_setmetatable( _lua, -2 ); lua_settable(_lua, -3); // increment the reference count as the lua now will unreference it once it's finished with the userdata for the pointer object->ref(); } std::string::size_type seperator = compoundClassName.find("::"); std::string libraryName = (seperator==std::string::npos) ? object->libraryName() : compoundClassName.substr(0, seperator); std::string className = (seperator==std::string::npos) ? object->className() : compoundClassName.substr(seperator+2,std::string::npos); lua_pushstring(_lua, "libraryName"); lua_pushstring(_lua, libraryName.c_str()); lua_settable(_lua, -3); lua_pushstring(_lua, "className"); lua_pushstring(_lua, className.c_str()); lua_settable(_lua, -3); lua_pushstring(_lua, "compoundClassName"); lua_pushstring(_lua, compoundClassName.c_str()); lua_settable(_lua, -3); luaL_getmetatable(_lua, "LuaScriptEngine.Object"); lua_setmetatable(_lua, -2); } else { lua_pushnil(_lua); } } void LuaScriptEngine::assignClosure(const char* name, lua_CFunction fn) const { lua_pushstring(_lua, name); lua_pushlightuserdata(_lua, const_cast(this)); lua_pushcclosure(_lua, fn, 1); lua_settable(_lua, -3); }